Pregunta

Quiero guardar un objeto de alguna clase derivada como una propiedad de otro objeto.

El problema para mí es conocer el tamaño del objeto a ser almacenado, ya que puede ser cualquier clase derivada de una clase base dada. No puedo asignar memoria para el objeto de la clase base, a la derecha, ya que es más pequeño. Supongo, typeof operador que también acaba de dar el tamaño de la clase base, ¿verdad?

Aquí está mi código de ejemplo. Por favor, vea los comentarios de entender lo que quiero decir. Perdón por la falta de originalidad ...

BaseA {};

DerivedA1 : BaseA {public: void property() { cout << 1; }};
DerivedA2 : BaseA {public: void property() { cout << 2; }};
// etc. - several derived classes.

BaseB   // Contains (or links to) an instance of class derived from BaseA.
{
public:
    BaseA * instanceA;

    BaseB (BaseA instanceAX)
    {
        // ??? => How to allocate memory for the object
        // I don't know the real type of?
        instanceA = new BaseA (instanceAX);
    }

    BaseB (BaseA instanceAX) { delete instanceA; }
};

main()
{
    DerivedA1 instanceA1;
    BaseB instanceB (instanceA1);

    // Use "property" regardless of which derived class it belongs to.
    instanceB.instanceA->property();
} 

Me podría almacenar un puntero en lugar del objeto en sí, que sería más fácil. Pero no estoy seguro de querer depender de la persona que llama para retener la propiedad objeto de la vida de instancia instanceB .

Gracias!

¿Fue útil?

Solución

Bueno, en primer lugar, ya que se pasa en su BaseA por valor, no por referencia o puntero, te conocen el tipo; es BaseA. BaseB fue copiado en un BaseA y que copia BaseA se envía a la función. Cualquier dato adicional en BaseB no está contenida en instanceAX. Esto se llama "rebanar".

Sin embargo, para responder a su pregunta, simplemente no lo hacen de esta manera. Se necesita una función clone () en su clase BaseB si se tiene la intención de trabajar de esta manera. Alternativamente, usted puede diseñar un puntero inteligente u otro objeto que pueda clonar la instancia para usted. Si busca mi nombre en comp.lang.c ++ junto con el clon () puede llegar a través de una discusión que tuve allí sobre esta última idea.

La función clon es, por supuesto, una función virtual que devuelve una copia del objeto actual:

struct BaseA
{
  virtual BaseA* clone() const = 0;
};

struct BaseB : BaseA
{
  BaseB* clone() const { return new BaseB(*this); }
};

Otros consejos

Veo dos posibilidades.

  • Dar BaseA una función miembro puramente virtual, tal vez llamada clone, que es responsable de generar una copia de la instancia que se llama sucesivamente. A continuación, el constructor de BaseB podría convertirse

    BaseB (BaseA const &instanceAX) { instanceA = instanceAX.clone (); }

  • También puedes, simplemente evite pasar punteros primas y usar boost::shared_ptr lugar. De esta manera, ya que es de referencia contado, la persona que llama no puede causar una destrucción prematura de la derivación BaseA que se utilizó para construir BaseB. Habría que ajustar BaseA * instanceA; leer boost::shared_ptr <BaseA> instanceA; A continuación, el constructor de BaseB podría ser:

    BaseB (boost::shared_ptr <BaseA> a) : instanceA (a) { }

El problema del primer abordaje es que algún programador cliente que hereda de, digamos DerivedA1 pueden olvidarse de poner en práctica clone en su derivación. El problema principal de la segunda aproach sería exigir que cada usuario de BaseB para asignar la propiedad objeto en el montón (Puesto que usted está haciendo una copia dentro BaseBs constructor de todos modos, al menos, el consumo total de memoria no se elevaría, sin embargo)

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