请参阅以下代码:
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
的初始化。
语言需要永远/永远不会被调用的代码的原因是什么?
答案 0 :(得分:3)
实际上,该语言不要求这样做。您的编译器未使用当前的C ++规则。
12.6.2p8说(重点是我的强调):
[注意:抽象类永远不是最派生的类,因此它的构造函数永远不会初始化虚拟基类,因此相应的 mem-initializers 可能会被省略。 - 结束说明]
我在C ++ 03中找不到这个规则,所以这是C ++中公认的缺陷,已经修复了。寻找支持C ++ 11的编译器更新。
我能找到的C ++ 03中最接近的相关规则是在12.6.2p6节中:
在执行任何不是派生类最多的类的构造函数时,应忽略命名虚拟基类的 mem-initializer 。