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

5
请看以下代码:

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() { }
};

这段代码无法编译,因为Renderable::Renderable()没有匹配的调用Component::Component()

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

由于Renderable是抽象类,因此无法直接实例化。由于它从Component中虚拟继承,所以它永远无法调用Component的初始化。

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


我也乐意听取更好的标题建议。 - Collin Dauphinee
我认为这就是“抽象”的意思 - 我们可以想象它,但它不是一个具体的对象。 - Dinesh
抽象类可以被编译器实例化。 - yngccc
(标题已更正,您说的是虚基类而不是抽象基类。在这里,组件实际上并不是抽象的。) - Ben Voigt
@yngccc 你能详细说明一下吗? - Daniel Kamil Kozar
1个回答

3
实际上,语言并不要求这样做。您的编译器未使用当前的C++规则。
12.6.2p8说(粗体是我为了强调):
[注意:抽象类永远不是最派生的类,因此其构造函数从不初始化虚拟基类,因此可以省略相应的mem-initializers。—结束注意]
我找不到这个规则在C++03中,所以这是C++中已经修复的一个公认的缺陷。寻找支持C++11的编译器更新。
我能找到的与之最相关的C++03规则是在第12.6.2p6节中:
命名虚拟基类的mem-initializer将在任何不是最派生类的类的构造函数执行期间被忽略。

gcc、clang和cl都需要一个初始化器。这是新的吗? - Collin Dauphinee
谢谢更新!这就解释了! - Collin Dauphinee
@dauphic:对于最初的虚假警报我感到抱歉。我知道最派生类会在非虚拟直接基类之前构造虚拟基类,但我假设它会查找直接继承类的构造函数参数。你能看出来我避免使用虚拟继承吗? - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接