Almacenar objetos de clase derivados en variables de clase base

Me gustaría almacenar instancias de varias clases en un vector. Como todas las clases heredan de la misma clase base, esto debería ser posible.

Imagina este progtwig:

#include  #include  using namespace std; class Base { public: virtual void identify () { cout << "BASE" << endl; } }; class Derived: public Base { public: virtual void identify () { cout << "DERIVED" << endl; } }; int main () { Derived derived; vector vect; vect.push_back(derived); vect[0].identify(); return 0; } 

Esperaba que imprimiera “DERIVADO”, porque el método “identificar” es virtual. En cambio, ‘vect [0]’ parece ser una instancia ‘Base’ y se imprime

BASE

Creo que podría escribir mi propio contenedor (probablemente derivado del vector) de alguna manera que sea capaz de hacer esto (tal vez con sólo punteros …). Solo quería preguntar si hay un método más C ++ ish para hacer esto. Y me gustaría ser completamente compatible con el vector (solo por conveniencia si otros usuarios alguna vez usan mi código).

Lo que estás viendo es Object Slicing .
Está almacenando el objeto de la clase Derivada en un vector que se supone que almacena objetos de la clase Base, esto lleva al corte de Objetos y los miembros específicos de la clase derivada del objeto que se está almacenando se cortan, así el objeto almacenado en el vector solo actúa como objeto de la clase base.

Solución:

Debes guardar el puntero al objeto de la clase Base en el vector:

 vector 

Al almacenar un puntero a la clase Base, no habría cortes y también se podría lograr el comportamiento polimórfico deseado.
Como usted solicita una forma C++ish de hacerlo, el enfoque correcto es usar un puntero inteligente adecuado en lugar de almacenar un puntero sin formato en el vector. Eso asegurará que no tenga que administrar manualmente la memoria, RAII lo hará automáticamente.

Estás experimentando cortar. El vector copia el objeto derived , se inserta uno nuevo de tipo Base .

TL; DR: No debe heredar de una clase públicamente copiable / movible.


De hecho, es posible evitar el corte de objetos en el momento de la comstackción: el objeto base no debería poder copiarse en este contexto.

Caso 1: una base abstracta

Si la base es abstracta, no se puede crear una instancia y, por lo tanto, no se puede experimentar el corte.

Caso 2: una base de concreto

Si la base no es abstracta, entonces se puede copiar (por defecto). Tienes dos opciones:

  • prevenir copia por completo
  • permitir copia solo para niños

Nota: en C ++ 11, las operaciones de movimiento causan el mismo problema.

 // C++ 03, prevent copy class Base { public: private: Base(Base const&); void operator=(Base const&); }; // C++ 03, allow copy only for children class Base { public: protected: Base(Base const& other) { ... } Base& operator=(Base const& other) { ...; return *this; } }; // C++ 11, prevent copy & move class Base { public: Base(Base&&) = delete; Base(Base const&) = delete; Base& operator=(Base) = delete; }; // C++ 11, allow copy & move only for children class Base { public: protected: Base(Base&&) = default; Base(Base const&) = default; Base& operator=(Base) = default; }; 

Usaría el vector para almacenarlos. Si dices vector , se producirá un corte.

Esto significa que tendrá que eliminar los objetos usted mismo después de haber eliminado los punteros de su vector, pero de lo contrario debería estar bien.