C++虛函數繼承與虛繼承

虛函數繼承和虛繼承是徹底不一樣的兩個概念。函數

虛函數繼承是解決多態性的,當用基類指針指向派生類對象的時候,基類指針調用虛函數的時候會自動調用派生類的虛函數,這就是多態性,也叫動態編聯。指針

虛繼承就是爲了節約內存,他是多重繼承中的特有的概念。適用於菱形繼承形式。對象

好比B繼承於A、C繼承於A、D繼承於B和C,顯然D會繼承兩次A(圖1)。所以,爲了節省空間,能夠將B、C對A的繼承定義爲虛擬繼承,而A就成了虛擬基類(圖2)。代碼以下:繼承

 A    A           A 
  \    /           / \ 
  B   C           B  C 
   \  /            \  / 
   D             D 
  (圖1)          (圖2)內存

class A; 
class B:vitual public A; 
class C:vitual public A; 
class D:public B,public C; 

虛繼承的時候子類會有一個指向本身虛函數表的指針,同時也會加入一個指向父類的虛類指針,而後還要包含父類的全部內容。it

虛繼承時若是子類父類都有虛函數,那麼它會從新創建一張虛表,不包含父類虛表的內容;而在普通的繼承中倒是在父類虛表的基礎上創建一張虛表。這就意味着若是虛繼承中子類父類都有各自的虛函數,在子類裏面就會有兩個虛函數表指針,一個指向父類的虛表,一個指向子類的虛表,而普通的繼承只有一個指向子類虛表的指針。代碼說明:class

class A
{
    int k;
public:
    virtual void aa(){};
};基礎

class B:public virtual A
{
    int j;
public:
    virtual void bb(){};
};變量

class C:public virtual B
{
    int i;
public:
    virtual void cc(){};
};vi

int main()
{
    cout << sizeof(A) << endl;
    cout << sizeof(B) << endl;
    cout << sizeof(C) << endl;
    system("pause");
    return 0;
}

輸出結果爲:8、20、32。

怎麼來的呢?類A中包含一個整型變量k(4字節),一個虛表指針(4字節),因此一共8字節。類B中,一個整型變量j(4字節),一個虛表指針(4字節),由於B虛繼承於A,全部會有一個指向類A的虛類指針(4字節),同時還要包含類A中的整型變量k(4字節)以及類A的虛表指針(4字節),因此一共20字節。類C同理。

若是將上述代碼改成普通繼承,那麼輸出結果爲:八、十二、16。沒有虛類指針,也不會有多個虛表指針  

相關文章
相關標籤/搜索