将派生类对象存储在基类variables中

我想将几个类的实例存储在一个向量中。 由于所有的类都从同一个基类inheritance,所以这应该是可能的。

想象一下这个程序:

#include <iostream> #include <vector> 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<Base> vect; vect.push_back(derived); vect[0].identify(); return 0; } 

我期望它打印“派生”,因为“识别”方法是虚拟的。 相反,“vect [0]”似乎是一个“基础”的实例,它打印

基础

我想我可以编写我自己的容器(可能来自vector),不知何故,这是能够做到这一点(也许只有指针…)。 我只想问是否有更多的C ++ ish方法来做到这一点。 我想完全向量兼容(只是为了方便,如果其他用户应该使用我的代码)。

你看到的是对象切片
您正在将Derived类的对象存储在一个应该存储Base类对象的向量中,这导致了Object切片,并且被存储的对象的派生类特定成员被切掉,因此存储在该向量中的对象只是作为基类的对象。

解:

你应该在vector中存储指向Base类对象的指针:

 vector<Base*> 

通过存储一个指向Base类的指针,就不会出现切片,而且您也可以实现所需的多态行为。
既然你要求C++ish是这样做的,正确的方法是使用一个合适的智能指针,而不是将原始指针存储在向量中。 这将确保您不必手动pipe理内存, RAII将自动为您执行此操作。

你正在经历切片。 vector复制derived对象,插入一个新的Basetypes。

TL; DR:你不应该从公开的复制/移动类inheritance。


实际上,可以在编译时防止对象切片:在此上下文中,基础对象不应该是可复制的。

案例1:一个抽象的基础

如果基础是抽象的,那么它不能被实例化,因此你不能体验切片。

案例2:一个具体的基地

如果基地不是抽象的,那么它可以被复制(默认)。 你有两个select:

  • 完全防止复制
  • 只允许儿童复制

注意:在C ++ 11中,移动操作会导致相同的问题。

 // 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; }; 

我会使用vector<Base*>来存储它们。 如果你说vector<Base> ,切片就会发生。

这意味着你必须删除实际的对象后,你已经删除了向量的指针,但否则你应该没问题。