2013-03-20 61 views
1

我有以下代碼:「可怕的鑽石」與多態性

class Base 
{ 
    public: 
     virtual void doSomething() = 0; 
}; 

class BaseImpl : public virtual Base 
{ 
    public: 
     virtual void doSomething() { 
     // something 
     } 
}; 

class BaseDerived: public virtual Base 
{ 
    public: 
     virtual void doSomething2() = 0; 
}; 

class BaseDerivedImpl: public BaseImpl, public BaseDerived 
{ 
    public: 
     virtual void doSomething2(){ 
     // sonething2 
     } 
}; 

然後,我有

Base* b = new BaseImpl(); 
b->doSomething();   // fatal error at this line (not in the method, but in the method invocation) 

的問題是,它甚至沒有進入該功能。

使用此類層次結構時出現錯誤嗎?

+2

您的代碼編譯[here](http://liveworkspace.org/code/yJL1f$29)。你使用什麼編譯器? – 2013-03-20 13:34:12

+0

是的,它被編譯。 GCC(4.7.2)。我有運行時錯誤 – user14416 2013-03-20 13:36:13

+1

你甚至沒有使用BaseDerived或BaseDerivedImpl - 如果你的聲明是Base * b = new BaseDerivedImpl;代替?無論如何也是如此。 – 2013-03-20 13:37:20

回答

2

由於OP忽略的評論,讓我在這裏回答這個問題:

是不是有毛病使用這種層次結構?

不,沒有錯。這是如何解決'可怕鑽石'問題的標準方式(實際上並不是那麼可怕)。

然而,鑽石甚至不進來在這個例子中發揮:

Base* b = new BaseImpl(); 

BaseImpl直接從Base衍生讓你擁有標準的單一繼承。您的代碼行爲相同,如果根本沒有定義BaseDerivedBaseDerivedImpl。你可以評論他們,應用程序仍然會崩潰。

然後您在此實例上調用doSomething並崩潰。的doSomething實現如下:

// something 

因此,我的結論是,// something結果與碰撞,但不可能說沒有看到該方法的實現。

+0

請注意,「可怕的鑽石」只有那些沒有花一兩分鐘時間看看它是如何工作的人可怕的。這並不難... – 2013-03-20 13:54:23

+0

雖然我不會責怪OP。文學充滿了對「可怕鑽石」的盲目反覆尖叫,很多人甚至不想知道細節。當然,你可以用它拍打你的腳,但它不是黑魔法 – 2013-03-20 13:56:30