虛擬函式及虛繼承總結
一. 虛擬函式
虛擬函式的使用是為了實現c++中的多型,即同一介面,不同實現,可用父類指標呼叫子類成員函式。虛擬函式是基於虛擬函式表(virtual table,v-table for short)來實現的。
每個包含虛擬函式的類都將分配一張虛擬函式表,虛擬函式表是一張地址表,解決繼承多型問題。虛擬函式表並不存在於類例項中,而是類例項生成一個指向虛擬函式表的指標。
多重繼承中將會針對各個基類生成指標,子類的虛擬函式將寫於第一個繼承的父類中。直接繼承比較簡單,不再贅述,下面說一下覆蓋繼承。程式執行平臺為64位編譯器。
`class A
{
private:
char data;
public:
A(){data = ‘A’;}
virtual void Show(){printf(“A\n”);};
virtual void DispA(){printf(“a\n”);};
};
class B
{
private:
int data;
public:
B(){data = ‘B’;}
virtual void Show(){printf(“B\n”);};
virtual void DispB(){printf(“b\n”);};
};
class C
{
private:
char data;
public:
C(){data = ‘C’;}
virtual void Show(){printf(“C\n”);};
virtual void DispC(){printf(“c\n”);};
};
class D : public A, public B, public C
{
public:
char data;
public:
D(){data = ‘D’;}
virtual void Show(){printf(“D\n”);};
virtual void DispD(){printf(“d\n”);};
};
`
D的物件記憶體如下所示:
由位元組對齊,可知sizeof(d)=48
在計算類的大小時,成員函式和靜態成員變數並不算在類物件的大小中,他們是與類關聯,並不與物件關聯。
父類成員函式在子類中或者重寫或者隱藏。
二.虛擬繼承
參考網址:>
虛擬繼承是為了解決子類中出現多次父類的成員物件和函式問題,例如B,C均繼承A,D繼承B,C,則在D中會拷貝兩次A的成員物件和函式。使用虛繼承就是為了D中只進行一次A的拷貝。
而使用虛擬繼承時會生成不同於指向虛擬函式表的指標。
class A
{
public:
virtual void aa() { }
virtual void aa2() { }
private:
char ch[3];
};
class B: virtual public A
{
public:
virtual void bb() { }
virtual void bb2() { }
};
很明顯a的大小為16byte,b虛擬繼承A,所以在b例項的記憶體中首先是虛擬繼承指標(指向虛基類拷貝在記憶體中的偏移量),然後是指向A虛擬函式表的指標,最後為ch。最終b的大小為24byte