2014-01-20 85 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:對於原始的虛警,感到抱歉。我知道大多數派生類將在非虛擬直接基礎之前構建虛擬基礎,但我假設它將查找構造函數參數的直接繼承類。你能告訴我避免虛擬繼承嗎? –

相關問題