2014-01-20 86 views
3

请看下面的代码:为什么抽象派生类需要初始化一个虚拟基类?

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继承的,所以它将永远无法调用Component的初始化。

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

+0

我也乐于提供更好的标题建议。 –

+0

我认为这就是“抽象”的意思 - 我们可以想到的东西,但不是一个具体的对象。 – Dinesh

+0

抽象类可以由编译器实例化。 – yngccc

回答

2

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

12.6.2p8说(为了强调粗体矿):

[注:一个抽象类是从来没有一个最派生类,因而其构造从未初始化虚拟基类,因此相应MEM-可以省略初始化器 - 注完]

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

在C++ 03的最接近的相关规则,我可以找到在部分12.6.2p6:

一个MEM-初始化命名一个虚基类应的任何构造函数的执行过程中被忽略不是最派生类的类。

+0

gcc,clang和cl都需要一个初始化程序。这是新的吗? –

+0

感谢您的更新!这解释了它! –

+0

@dauphic:对于原始的虚警,感到抱歉。我知道大多数派生类将在非虚拟直接基础之前构建虚拟基础,但我假设它将查找构造函数参数的直接继承类。你能告诉我避免虚拟继承吗? –

相关问题