大多数派生类类型都没有调用虚函数

时间:2012-05-10 19:30:27

标签: c++ templates virtual-functions

编辑已解决并重新发布为示例程序

情景如下:

类层次结构:

class Base
{
public:
   virtual void output() = 0;
private:
   int a;
};

class Derived_1 : public Base
{
public:
   virtual void output()
   {
      cout << "Derived_1" << endl;
   }
};

class Derived_2 : public Derived_1
{
public:
   virtual void output()
   {
      cout << "Derived_2" << endl;
   }
};

实施:

Derived_2* obj = reinterpret_cast<Derived_2*>(new Derived_1());
obj->output();

这将输出“Derived_1”而不是“Derived_2”。我相信这对你们大多数人来说并不是什么新鲜事,但是在我的应用程序中制作我的一些工厂函数时,我没有想到这一点。

3 个答案:

答案 0 :(得分:3)

编辑此答案基于发布的原始代码。在看到截断的示例按预期工作后,OP更新了代码示例。


您的代码不完全正确,但发生此类事件的最常见原因是,当您尝试覆盖并且创建了重载时,您没有完全正确地获取签名。当您通过基类调用时,它仍将调用正确定义的基类。

签名中的所有内容都很重要 - 一个常见的错误是方法的常量是签名的一部分。

答案 1 :(得分:3)

您正在分配Value_object_data个对象,而不是Value_object_uint32。您将其作为Value_object_uint32进行投射的事实一无所获。实际对象的虚拟表不知道Value_object_uint32;在虚构函数表中,它是在构造错误时构造的,format指向Value_object_data的{​​{1}}。强指向指向实际对象的指针类型无法解决问题。

给定层次结构中所有基类和继承类的构造函数从最派生到根调用,每个类只调用一次。这意味着,您不必显式调用基类构造函数。它会自动调用。如果需要指定应该使用几个基类构造函数中的哪一个,那么也可以这样做:

format

当然,class Base { public: Base() {} // default constructor Base(int a) {} }; class Derived { public: Derived() : Base() { } Derived(int a) : Base(a) // Select the Base ctor that takes an int, instead of the default { } }; int main() { Derived d1; // Calls Derived() and Base() ctors in this order Derived d2(5); // Calls Derived(5) and Base(5) in this order } 构造函数不需要调用Derived(int a)构造函数。在这种情况下,Base(int)构造函数将自动调用。

答案 2 :(得分:0)

至少,new_VO_data()方法已被破坏。由于可变的虚拟表大小和可变填充,它可能或可能不起作用,它们是标准的任意值并且取决于编译器选项。简单地说,行为是未定义的。