Pregunta

Tengo una clase con un puntero (no inteligente) a un objeto de la interfaz (llamémoslo pInterface) y estoy creando una clase anidada que también necesita acceso a esa interfaz. Voy a sortear esto pasando el puntero a la interfaz al constructor de la clase anidada de esta manera:

CNestedClass someClass( pInterface, ... );

Sin embargo, no estoy seguro de cuál es la mejor manera de almacenar este puntero en la clase anidada. Podría usar:

1) A scoped (or other smart) pointer (to the original object)
2) A pointer to a pointer 

¿Qué sugerirían ustedes y por qué?

EDITAR: Debo aclarar: la clase anidada deberá llamar a los métodos en el objeto de la interfaz, sin embargo, no lo crea (o modifica el objeto 'apuntado' a), la clase principal es responsable de eso.

¿Fue útil?

Solución

El uso de un puntero a un puntero es si cualquiera de las clases puede alterar el valor del puntero, por ejemplo, eliminando el objeto existente y reemplazándolo por uno nuevo. Esto permite que ambas clases sigan utilizando el mismo objeto al eliminar la referencia de puntero a puntero.

Si no le preocupa, asegúrese de que el objeto permanezca válido durante toda la vida útil de ambas clases.

  • Si la clase anidada es más corta, realmente no tiene que preocuparse.
  • Si es lo mismo, siempre que realice la limpieza en el orden correcto (por ejemplo, primero la clase anidada, luego el objeto), una vez más, no tiene que preocuparse
  • Si la clase anidada podría persistir después de destruir al propietario, debe implementar una forma de garantizar que el objeto también persista.

Si necesita garantizar la vida útil del objeto, puede hacerlo a través de la semántica de conteo de referencias, ya sea manualmente o mediante una interfaz de puntero inteligente.

Para un puntero inteligente, entonces boost :: shared_ptr sería una buena opción. shared_ptr permite que la propiedad de un objeto sea una cantidad compartida de múltiples punteros. Cuando el último shared_ptr sale del ámbito, el objeto se elimina.

(tenga en cuenta que este no es el caso con auto_ptr, donde un objeto es de propiedad exclusiva).

Cosas a tener en cuenta;

  1. Cuando use boost :: shared_ptr, asegúrese de que la clase anidada tenga una copia de shared_ptr y no una referencia / puntero.
  2. std :: auto_ptr se comporta de manera muy diferente, los objetos son de propiedad exclusiva y no se comparten
  3. boost :: shared_ptr solo puede trabajar con objetos de pila, por ejemplo, punteros devueltos desde una llamada a 'nuevo'

Ejemplo:

typedef boost::shared_ptr<Interface> shared_interface;

class NestedClass
{
  shared_interface mInterface; // empty pointer
}

void NestedClass::setInterface(shared_interface& foo)
{
  mInterface= foo; // take a copy of foo.
}

void ParentClass::init( void )
{
  // mInterface is also declared as shared_interface
  mInterface = new Interface();
  mNestedClass->setInterface(mInterface);
}

Otros consejos

La otra razón por la que puede querer usar un puntero a un puntero sería si el código externo pudiera cambiar el valor del puntero original (por ejemplo, haga que apunte a un nuevo objeto, o establézcalo en NULL) después de soltar el objeto al que apunta). Sin embargo, en mi opinión, es una mala práctica cambiar un puntero después de dárselo a otra persona.

Entonces, si ni el código externo ni la clase anidada cambian el puntero, simplemente guárdelo en la clase anidada como una copia del puntero original como una variable miembro (campo).

Pase la dirección de un puntero a su interfaz (IMyInterface ** ppInterface), y complete el puntero si la clase lo implementa.

La clase puede enviar este puntero a esa interfaz y completar el puntero * ppInterface. Si la clase no implementa esta interfaz, puede establecer * ppInterface en NULL.

Básicamente, estás compartiendo un puntero al mismo objeto entre dos objetos diferentes. Si no está utilizando ningún puntero inteligente, simplemente almacene el puntero al objeto compartido. Debe tener cuidado con la propiedad del objeto compartido, es decir, qué objeto es responsable de desasignar el objeto compartido y notificar a los demás que se ha ido.

class Outer
{
    class Inner
    {
    };
};

Como un objeto de Outer solo tiene un puntero RAW a un objeto pInterface, esto implica que el objeto Outer no posee ni tiene ningún control sobre la vida útil del objeto pInterface. Por lo tanto, esperamos que haya alguna garantía de que el objeto pInterface viva tanto como el objeto externo; En este caso, no hay ninguna razón para usar un puntero, podría usar una referencia (suponiendo que no haya una situación en la que pInterface sea NULL).

¡Cómo mantiene Inner su "referencia" (no la referencia de C ++) depende y realmente necesitamos más información sobre la relación entre los objetos involucrados!

  • ¿Cuál es la relación entre los objetos internos y externos?
  • ¿Cuál es la vida útil de un objeto interno en relación con el objeto externo del que heredó el puntero de interfaz?
  • ¿Cuál es la garantía de que un objeto exterior tiene una vida útil más corta que un objeto de interfaz?

etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top