【问题标题】:Virtual function not called on most derived class type大多数派生类类型上未调用虚函数
【发布时间】:2012-05-10 19:30:26
【问题描述】:

Edit Solved and Reposted 作为示例程序

场景如下:

类层次结构:

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

【问题讨论】:

  • 不应该derived_2 继承自derived_1?和derived_1 来自Base?这只是一个错字吗?
  • 看起来您缺少代码的重要部分。例如,derived_1 是否从 Base 派生(也,您的意思是 base,对)。派生_2 派生自派生_1 吗?基地?
  • 我认为derived_2 不是从您的示例中的任何内容派生的错字? derived_1 也不是从任何东西派生而来的。
  • do_something 仍然是私有的;只需发布您的实际代码
  • 现在Value_object_data::new_VO_data() 不见了,但我开始明白了。不过,这家reinterpret_cast 的公司闻起来很糟糕。

标签: c++ templates virtual-functions


【解决方案1】:

您分配的是Value_object_data 对象,而不是Value_object_uint32。您将其转换为 Value_object_uint32 的事实不会改变任何事情。实际对象的虚拟表不知道Value_object_uint32format 在其虚函数表中,即在 err... 构造时构造,指向 Value_object_dataformat。对指向实际对象的指针类型进行强力武装并不能解决问题。

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

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() 构造函数将被自动调用。

【讨论】:

  • 糟糕,我已经重新发布了一个示例问题而不是实际代码,因为我认为它更容易理解。抱歉,这使您的回答似乎没有意义。
  • @Ian 没关系,任何好奇的人都可以查看修订历史。
【解决方案2】:

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


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

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

【讨论】:

  • 好吧,我会继续寻找。大多数情况下,我想确保模板不会引起任何问题。
  • 我将您的代码粘贴到这里 codepad.org/faJmyhKS 并修复了语法错误。它有效。
  • 感谢您发布它,但我看不出我的示例代码与我发布的上述截断版本的实际代码有何不同。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-04
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多