从父母到孩子的std :: bad_cast?

时间:2010-06-08 09:49:10

标签: c++ casting

为简单起见,

class Parent {}
class Child1 : Parent {}
class Child2 : Parent {}

在其他地方,我创建了Child1和Child2的实例,并将其存储在Parent:

下的相同向量中
// . . . in .h file, for example
vector<Parent> vector_of_parent;

// . . . in one particular method
Child1 c1; 
Child2 c2; 
vector_of_parent.push_back(c1);
vector_of_parent.push_back(c2);
// . . .

然后在另一种有权访问vector_of_parent的方法中,我尝试了

 void doSomething(Parent& some_child) { 
 // wrapped in a try block somehow...
 Child1& c = dynamic_cast<Child1&> some_child;
 // do something if the cast is successful
 }

 void otherMethod() {
      doSomething(vector_of_parent.at(0)); // vector_of_parent.at(0) is a Child1
 }

为什么在调用otherMethod()时会出现std:bad_cast?

3 个答案:

答案 0 :(得分:7)

您的std::vector被声明为std::vector<Parent>。它仅包含Parent的实例 - 当您插入Child1Child2个实例时,它们会获得sliced

如果要使用具有公共基类Parent的多态对象向量,则需要使用指针容器(或者,为了便于生命和内存管理,使用智能指针)。

要考虑的适当容器类型包括std::vector<Parent*>std::vector<std::tr1::shared_ptr<Parent> >boost::ptr_vector<Parent>

除非您对手动内存管理非常熟悉,否则我建议不要使用std::vector<Parent*>


此外,您需要使用公共继承而不是私有,并且基类必须具有虚拟析构函数。我假设你为了简洁而把它们留下了。

答案 1 :(得分:6)

当你说:

vector<Parent> vector_of_parent;

您创建了父矢量 - 它不可能包含Child对象。如果你想要一个多态C ++容器,它必须包含基类指针。你的动态演员表失败了,因为你应用它的东西总是Parent而不是Child。

此外,您的代码并不清楚,但为了使用dynamic_cast,您的基类必须至少包含一个虚函数。

答案 2 :(得分:3)

vector<Parent> vector_of_parent;

您正在创建Parent个对象的向量。请注意,vector将始终创建传递的对象的副本。因此,当您执行vector_of_parent.push_back(c1);时,会创建一个c1副本,其代码类似于(为简单起见,我忽略了分配器)T* pObj = new T(c1);。由于此处的T类型为Parent,因此创建的副本的类型为Parent。所以基本上是什么,子对象被切片以创建父对象。现在,如果您尝试将此Parent对象动态广播为Child类型,则会抛出异常。