为什么抽象派生类需要初始化虚拟基类?

时间:2014-01-20 01:53:57

标签: c++ inheritance virtual-inheritance

请参阅以下代码:

struct Object;

struct Component
{
    Component(Object* obj) { }
};

struct Renderable : public virtual Component
{
    virtual void Render() = 0;
};

struct AnimationRenderer : public Renderable
{
    AnimationRenderer(Object* obj) : Component(obj) { }
    virtual void Render() { }
};

无法编译,因为来自Component::Component()的{​​{1}}没有匹配的调用。

我可以通过给Renderable::Renderable() Renderable构造函数(例如Renderable() : Component(NULL) { })来使这个示例工作,即使Renderable永远无法初始化Component

因为Renderable是一个抽象类,所以它永远不能直接实例化。因为它实际上是从Component继承的,所以永远无法调用Component的初始化。

语言需要永远/永远不会被调用的代码的原因是什么?

1 个答案:

答案 0 :(得分:3)

实际上,该语言不要求这样做。您的编译器未使用当前的C ++规则。

12.6.2p8说(重点是我的强调):

  

[注意:抽象类永远不是最派生的类,因此它的构造函数永远不会初始化虚拟基类,因此相应的 mem-initializers 可能会被省略。 - 结束说明]

我在C ++ 03中找不到这个规则,所以这是C ++中公认的缺陷,已经修复了。寻找支持C ++ 11的编译器更新。

我能找到的C ++ 03中最接近的相关规则是在12.6.2p6节中:

  

在执行任何不是派生类最多的类的构造函数时,应忽略命名虚拟基类的 mem-initializer