child从中派生的对象base
class base
{
public:
virtual int get() const { return 0;}
~virtual base(){}
};
class child : public base
{
public:
virtual int get() const override { return 1; }
};
Run Code Online (Sandbox Code Playgroud)
当加入容器时切成薄片,例如
std::vector<base> bases;
bases.push_back(child());
Run Code Online (Sandbox Code Playgroud)
并且下面的代码返回0
bases.at(0).get();
Run Code Online (Sandbox Code Playgroud)
即使push_back的签名是:
void push_back( const T& value );
void push_back( T && value );
Run Code Online (Sandbox Code Playgroud)
这不应该招致切片的对象.
例如,下面的代码导致bad_cast
dynamic_cast<child &>(bases.at(0))
Run Code Online (Sandbox Code Playgroud)
而与基地的孩子打电话则表现出多态行为
void toto(base const & e)
{
std::cout << e.get() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这意味着对象不再是一个孩子; 切片在哪里?实际发生了什么?
是否有可能设置base或child应对放置在容器中并且对象不会失去其多态性?
这是一个基本原理问题,并且已经知道一个对象被复制了,所以请不要建议指针/ shared_ptr,因为这已在其他地方得到解决.
切片在哪里?
您的
std::vector<base> bases;
Run Code Online (Sandbox Code Playgroud)
存储普通base对象.你不能在那里添加任何东西,只能添加一个base对象.因此,如果你在那里添加了一个对象,那么它就是一个base对象.如果你传递了另一种类型push_back,它将被转换为base(如果可能的话); 在你的情况下,这意味着切片.我不认为你对切片在std::vector特定实现的函数内部发生的确切位置感兴趣.
是否有可能设置
base或child应对放置在容器中并且对象不会失去它的多态性?
为了保持多态性,您需要存储指向bases 1的指针.除了容器之外,还有很多方法可以复制它.最简单的方法是写一些类似的东西
child c;
...
std::vector<base*> v;
v.push_back(new child(c)); // and yes, smart pointers are better
Run Code Online (Sandbox Code Playgroud)
您当然可以添加包装器push_back以避免new每次键入.
1您无法在向量中存储引用,但请参阅此问题以获取更多选项.