4

據我所知,菱形繼承產生歧義,它可以通過virtual Base Classes使用繼承迴避的是,問題不是它。當類是多態時,問題是關於菱形層次結構中派生最多的類的大小。下面是一個示例代碼和輸出樣本:菱形多態繼承:大多數的sizeof派生類

#include<iostream> 

using namespace std; 

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

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

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

class Derived3:public Derived1,public Derived2 
{ 
    public: 
     virtual void doSomething(){} 
}; 

int main() 
{ 
    Base obj; 
    Derived1 objDerived1; 
    Derived2 objDerived2; 
    Derived3 objDerived3; 

    cout<<"\n Size of Base: "<<sizeof(obj); 
    cout<<"\n Size of Derived1: "<<sizeof(objDerived1); 
    cout<<"\n Size of Derived2: "<<sizeof(objDerived2); 
    cout<<"\n Size of Derived3: "<<sizeof(objDerived3); 

    return 0; 
} 

輸出I得到的是:

Size of Base: 4 
Size of Derived1: 4 
Size of Derived2: 4 
Size of Derived3: 8 

據我所知Base包含虛擬成員函數,因此,
的sizeof基地= vptr的的尺寸= 4在這種環境下

類似的情況Derived1 & Derived2類。

這裏是我的問題涉及到上述方案:
怎麼樣Derived3類對象的大小,這是否意味着Derived3類有2 vptr的?
Derived3類如何與這2個vptr一起工作,有關它使用的機制的任何想法?
Sizeof類的大小保留爲未由標準定義的編譯器&的實現細節(因爲虛擬機制本身是編譯器的實現細節)?

+1

關於標準問題。是的,如何實現虛擬方法的機制是實現細節,而不是指定的。是的,sizeof'的實際結果也是一個實現細節,它主要取決於指針大小,如果你在64位平臺上,你會看到'8/8/8/16'。 – 2011-03-31 18:12:38

回答

4

是,Derived3有兩個虛表指針。如果您按價值訪問它,它會使用Derived3版本,或者從父項中選取一個函數,或者表示如果它無法確定,則它是不明確的。

在兒童的情況下,它使用對應於該被真實多態中使用的父1/2 V表。你沒有使用虛擬繼承

注意正確:我相信Derived1和2應從Base幾乎繼承。 sizeof(Derived3)仍然似乎是8,因爲它仍然有兩個可能的父母,可以被視爲Derived3。當你轉換到其中一個父代時,編譯器會實際調整對象指針以獲得正確的vtable。

此外,我應該指出,任何虛函數表相關的具體實施,因爲竟然沒有標準虛函數表的任何提及。

+0

謝謝,我糾正了Derived1&Derived2幾乎從Base繼承的錯誤。 O/P仍然是一樣的。 – 2011-03-31 16:32:42

1

我想你想知道的東西完全是實現特定的。 你不應該假設類的大小。

編輯:雖是好奇的是一個公認的質量;-)

1

考慮一個稍微不同的情況下:

struct B { virtual void f(); }; 
struct L : virtual B { virtual void g(); }; 
struct R : virtual B { virtual void h(); }; 
struct D : L, R {}; 

在典型的實現中,L ::克將在相同的位置中(在 索引0表示)L的虛函數表爲R: h在R的vtable中。現在考慮 給出下面的代碼會發生什麼:

D* pd = new D; 
L* pl = pd; 
R* pr = pd; 
pl->g(); 
pr->h(); 

在最後兩行,編譯器將生成的代碼在虛函數表的相同位置找到該功能的 地址。因此,通過pl訪問的 vtable不能與通過pr訪問的那個(或其中的前綴 )相同。因此,完整的對象至少需要兩個vptr,以指向兩個不同的vtable。

+0

實際上在典型的實現中'f'可能會在虛擬表中的'g'或'h'之前,所以當使用'L'或'R'多態作爲'B時不需要調整'(即'L'表格的佈局將是'B'表格佈局的超集,所以它的'B'視圖符合'B'嘗試)。 – 2011-03-31 18:11:12

+0

@Matthieu M.是的。在很多實現中,vtable將以一個或多個特殊指針開始,例如type_info信息,接着是基類中的虛函數,然後是該類的虛函數,這些函數不是覆蓋一個基地。但是,事實仍然是,L的vtable與g的vtable有相同的地方,所以同樣的vtable不能用於D. – 2011-04-01 07:51:04

+0

中的L和R。在很多實現中都是這樣。構建更智能的vtables需要全面的程序分析/鏈接時間優化。 – 2011-04-01 12:23:30