2011-07-08 19 views
4
struct B { int i; }; 
struct D1 : virtual B {}; 
struct D2 : B {}; // <-- not virtual 
struct DD : D1, D2 {}; 

上面已經編碼,還是編譯器要求D2也成爲virtual爲什麼單個虛擬繼承不足以解決可怕的鑽石問題?

DD d; 
d.i = 0; // error: request for member `i' is ambiguous 

我不明白的是,一旦你已經促使編譯器Bvirtual相對於DD(通過D1 )那麼爲什麼它仍然i含糊不清?

(如果我沒有記錯正確的,舊的VC++(2006年),是有足夠的能力來辨認出這只是單virtual繼承)

回答

7

B對於DD來說不是虛擬的 - 它相對於D1是虛擬的。在D2創建時,它包含B的完整副本。因此,現在DD有兩個B實現:一個作爲D2的一部分,另一個作爲D2的一部分(由D1指向)。並且有兩份i,使用它確實含糊不清。

只好D2也用虛擬繼承,而不是含B的副本,它會包含一個指針到B的實例D1也被指向,和DD會含有B.

只有一個實例

我會盡力來說明內存佈局,希望這次出來吧...:

你的情況下,一個虛擬繼承和一個非虛 -

| D1 | D2 + B | B | 
+--+-------+----------+---------+ 
| vptr to B   ^
+-----------------------| 

有D1和D2幾乎繼承 -

| D1 | D2 | B | 
+--+-----+---+----+-------+ 
|   |  ^
+---------+---------| 
2

您必須閱讀Diamond problem。在「方法」標題下,對於CPP,您的案例已明確提及,您的觀察與此處解釋的觀察相符。

+0

這是一個很好的鏈接,但正如你所說;它顯示了觀察。我想知道**背後的原因**。 (簡而言之)發生了什麼。 – iammilind

+0

我認爲關於[虛擬繼承](http://en.wikipedia.org/wiki/Virtual_inheritance)的文章可能會更深入地理解引擎蓋下發生的事情。 – eran

+0

維基百科鏈接不是答案。 – cHao

2

該標準要求d.i在這種情況下必須是不明確的。 ISO/IEC 14882:2003第10.1.6節涵蓋了具有給定類型的虛擬和非虛擬基類的類。