1

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

场景如下:

类层次结构:

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”。我敢肯定这对你们大多数人来说并不新鲜,但这是我在应用程序中创建一些工厂函数时没有想到的。

4

3 回答 3

3

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


您的代码并不完全正确,但发生这种情况的最常见原因是您在尝试覆盖时没有完全正确地获得签名,而是创建了重载。当您通过基类调用时,它仍然会调用正确定义的那个。

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

于 2012-05-10T19:37:51.723 回答
3

您正在分配一个Value_object_data对象,而不是Value_object_uint32. 您将其转换为 a 的事实Value_object_uint32没有任何改变。实际对象的虚拟表不知道Value_object_uint32; 在 err... 构造时构造的虚函数表中,format指向Value_object_data's 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)构造函数。在这种情况下,Base()构造函数将被自动调用。

于 2012-05-10T21:23:16.317 回答
0

至少,new_VO_data()方法被打破了。由于可变虚拟表大小和可变填充,它可能工作也可能不工作,这在标准上是任意的并且取决于编译器选项。简单地说,行为是未定义的。

于 2012-05-10T21:22:05.273 回答