代码之家  ›  专栏  ›  技术社区  ›  polyglot

从父级到子级的强制转换错误?

  •  1
  • polyglot  · 技术社区  · 15 年前

    为简单起见,

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

    在其他地方,我创建了child1和child2的实例,并将其存储在父项下的同一个向量中:

    // . . . 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 回复  |  直到 15 年前
        1
  •  7
  •   JoeG    15 年前

    你的 std::vector 被宣布为 std::vector<Parent> . 它只保存 Parent -当你插入 Child1 Child2 实例,他们得到 sliced .

    如果要使用一个多态对象的向量,该向量的公共基类为 起源 ,您需要使用指针容器(或者,为了方便使用寿命和内存管理,智能指针)。

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

    我建议反对 std::vector<父级*> 除非你对手动记忆管理很满意。


    另外,您需要使用公共继承而不是私有继承,并且基类必须有一个虚拟析构函数。不过,我想你是为了简洁起见才把这些忘了。

        2
  •  6
  •   anon    15 年前

    当你说:

    vector<Parent> vector_of_parent;
    

    创建父对象的向量-它不能包含子对象。如果你想要一个多态C++容器,它必须包含基类指针。动态强制转换失败,因为应用它的对象总是父对象而不是子对象。

    另外,代码中还不清楚,但是为了使用动态类型转换,您的基类必须至少包含一个虚拟函数。

        3
  •  3
  •   Naveen    15 年前
    vector<Parent> vector_of_parent;
    

    你正在创建一个向量 Parent 物体。请注意,矢量将始终创建一个 复制 传递的对象。所以当你这样做的时候 vector_of_parent.push_back(c1); C1的副本是用类似代码创建的(为了简单起见,我忽略了分配器) T* pObj = new T(c1); . 因为这里t的类型是 起源 ,创建的副本属于类型 起源 . 所以基本上发生的是子对象被切片,从中创建父对象。现在,如果你试着动态投射这个 起源 对象到 Child 键入它将引发异常。