2011-11-19 11 views
9

¿Cuál es una buena forma de compartir una instancia de un objeto entre varias clases en una jerarquía de clases? Tengo la siguiente situación:¿Cuál es una buena forma de compartir un objeto entre clases?

class texture_manager; 

class world { 
    ... 
    std::vector<object> objects_; 
    skybox skybox_; 
} 

Actualmente he implementado texture_manager como un conjunto unitario, y los clientes llamar a su método de instancias desde cualquier parte del código. texture_manager debe ser utilizado por object s en el vector objects_, por skybox_, y posiblemente por otras clases que pueden o no ser parte de la clase world. Como estoy tratando de limitar el uso de singletons en mi código, ¿recomienda alguna alternativa a este enfoque? Una solución que me vino a la mente sería pasar una referencia texture_manager como argumento para los constructores de todas las clases que necesitan acceder a ella. Gracias.

+1

¿Por qué no declarar simplemente una instancia global de su texture_manager? Los Globales no son malvados si se manejan correctamente. Y no son menos o más peligrosos en un entorno enhebrado que cualquier otra instancia transmitida a múltiples clientes ... – Mordachai

Respuesta

10

La respuesta general a esa pregunta es usar ::std::shared_ptr. O si no tiene eso, ::std::tr1::shared_ptr, o si no tiene eso, ::boost::shared_ptr.

En su caso particular, yo recomendaría uno de los pocos enfoques diferentes:

  1. Una posibilidad es, por supuesto, el enfoque shared_ptr. Básicamente pasas tu puntero a todos los que necesitan el objeto, y se destruye automáticamente cuando ninguno lo necesita más. Aunque si su administrador de texturas va a terminar con punteros a los objetos que apuntan hacia él, está creando un ciclo de referencia, y tendrá que manejarse con mucho cuidado.

  2. Otra posibilidad es simplemente declararlo como una variable local en main y pasarlo como un puntero o referencia a todos los que lo necesiten. No se irá hasta que su programa haya terminado de esa manera, y no debería tener que preocuparse por la gestión de la vida. Un puntero o referencia simple está bien en este caso.

  3. Una tercera posibilidad es uno de los tipos de usos vagamente aceptables de algo así como un singleton. Y esto merece una explicación detallada.

Usted hace un singleton cuyo único trabajo es dar consejos útiles para las cosas. Una característica clave que tiene es la capacidad de decirle a qué cosa darle un puntero. Es como una fábrica global configurable.

Esto le permite escapar de los enormes problemas de prueba que crea con un singleton en general. Solo dígale que entregue un puntero a un objeto auxiliar cuando llegue el momento de probar cosas.

También le permite escapar del problema de control de acceso/seguridad (sí, también crean problemas de seguridad) que representa un singleton por el mismo motivo. Puede decirle temporalmente que pase un puntero a un objeto que no permite el acceso a las cosas que la sección de código que está a punto de ejecutar no necesita acceso. Esta idea generalmente se conoce como el principio de la mínima autoridad.

La razón principal para usar esto es que le ahorra el problema de averiguar quién necesita su puntero y dárselo. Esta es también la razón principal para no usarla, pensando que a través de ella es bueno para usted. También introduces la posibilidad de que dos cosas que esperaban obtener el mismo puntero para un administrador de texturas en realidad obtienen punteros a un administrador de textura diferente debido a un flujo de control que no anticipabas, que es básicamente el resultado del pensamiento descuidado que te causó para usar el Singleton en primer lugar.Por último, los Singleton son tan horribles que incluso este uso más benigno de ellos me provoca comezón.


En lo personal, en su caso, recomendaría enfoque # 2, sólo la creación en la pila en main y pasando un puntero a donde sea necesario. Le hará pensar con más cuidado sobre la estructura de su programa, y ​​este tipo de objeto probablemente debería vivir durante toda la vida de su programa de todos modos.

+2

Creo que usar algún tipo de puntero compartido aquí es solo una forma de ir de puntillas alrededor de lo difícil (pero importante) discusión sobre quién es el propietario del objeto 'texture_manager'. ¿Realmente debería ser destruido tan pronto como nadie tenga una referencia sobre él? –

+1

Pensé en eso, sin embargo, pasar un shared_ptr por la jerarquía de clases parece engorroso, y espero encontrar una solución alternativa. ¿O no es esto lo que tenías en mente? –

+0

@FrerichRaabe: Sí, lo puse como el primer corte del 'consejo estándar'. Es en lo que la pregunta inmediatamente me hizo pensar. Pero lo analicé con más profundidad y actualicé mi respuesta. – Omnifarious

Cuestiones relacionadas