2013-05-15 210 views
8

我見過很多例子說明了多繼承的危險。爲什麼鑽石死亡而不是死亡三角

的例子是像通常的B類和C延伸A類,d延伸類B和C.

B和C二者覆蓋從A的方法,例如說,等於();

然後當調用D.equals();它不知道哪一個從其父應該叫

提供的equals()在D

從我看到的卻是沒有​​被覆蓋,是不是A級在這個例子中多餘的?如果我們從這個層次結構中刪除A並且只看B和C,如果B和C都有方法equals(),那麼當D擴展B和C時,它仍然會有同樣的問題,所以它不是真的死亡三角?

我不確定我的假設是否會導致某些其他語言的編譯時錯誤。

希望有人能爲我澄清它。

+3

不會讓它成爲'死亡V' – Craig

+0

我認爲這個設計相關問題更適合http://programmers.stackexchange.com/。 –

+0

我認爲「鑽石」只是說明了B類和C類都擴展了A類,儘管A本身不會造成任何麻煩。 – Janman

回答

1

D extends B and C如果不覆蓋方法equals(),其在B和C來實現,沒有歧義 - d可以使用B.equals()C.equals()

隨着另一方面金剛石結構,如果d調用A.equals()和B和C覆蓋它,你不知道哪種方法被調用B.equals()C.equals()

+1

你是說你好像在說什麼?如果'B'和'C'中的'equals'方法完全不同,該怎麼辦?如果'D'可以使用'B'或者''C'',那麼在我看來,這是一種模糊性。應該選擇哪一個? – paxdiablo

+0

我的意思是從執行的角度來看沒有歧義。 –

+0

好吧,現在你已經失去了我。如果'B.equals()'返回一個體面的值,'C.equals()'也返回該值,但格式化硬盤後,'D.equals()'應該做什麼?無論如何,這似乎是一個騙局,所以它可能應該被關閉。 – paxdiablo

0

你說得對,沒有必要存在A來顯示多重繼承的問題。

下面的代碼(如克雷格雄辯地把它放在一個評論「死亡V」)就足夠了:

#include <iostream> 

class xyzzy { 
    public: virtual int get (void) { return 7; } 
}; 

class plugh { 
    public: virtual int get (void) { return 42; } 
}; 

class twisty: public xyzzy, public plugh { 
}; 

int main() { 
    twisty passages; 
    std::cout << passages.get() << '\n'; 
    return 0; 
} 

如果您嘗試進行編譯,您可以:

testprog.cpp: In function ‘int main()’: 
testprog.cpp:16:24: error: request for member ‘get’ is ambiguous 
testprog.cpp:8:14: error: candidates are: virtual int plugh::get() 
testprog.cpp:4:14: error:     virtual int xyzzy::get() 

不過,請記住,您可以明確選擇你想要的東西類似於:

std::cout << passages.plugh::get() << '\n'; 

關於鑽石問題here的更多信息,包括爲什麼它實際上是一個不同的問題。

+0

由於顯式調用語法'passages.xyzzy :: get()'存在,所以人們稱它爲「死亡」,這很奇怪,並且讓你的意圖變得明顯。 – nurettin

+0

我認爲我現在理解得更好,我認爲這會導致編譯錯誤,因爲鑽石示例不會導致編譯錯誤,但會導致運行時錯誤? – grumpynerd