虛函數繼承和虛繼承是徹底不一樣的兩個概念。函數
虛函數繼承是解決多態性的,當用基類指針指向派生類對象的時候,基類指針調用虛函數的時候會自動調用派生類的虛函數,這就是多態性,也叫動態編聯。指針
虛繼承就是爲了節約內存,他是多重繼承中的特有的概念。適用於菱形繼承形式。對象
好比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。沒有虛類指針,也不會有多個虛表指針