1.問題:多重繼承 ==》 派生類物件中記憶體重複 ==》 訪問衝突 記憶體浪費
2.解決:對出現多份的資料在最近的繼承前加viture
3.虛繼承時,虛基類指標vbptr指向虛基類表vbtable,虛基類表中存放的就是資料相對於虛基類指標的偏移,從而根據偏移找到資料
vbptr ==> vbtable
vbtable 中:
0 當前最近作用域的偏移 - vbptr的偏移
1 虛繼類資料的起始偏移 - vbptr的偏移
虛基類構造優先順序大於普通基類
記憶體布局:先非虛基類,後 虛基類
1.
class a
public:
int ma;
};class b: virtual public a
public:
int mb;
};class c : virtua public a
public:
int mc;
};class d : public b, public c
public:
int md;
};當a為虛基類,虛繼承於b.c時:
若為多繼承時,記憶體布局如下:
虛繼承的記憶體布局如下:
};
當a為虛基類,虛繼承於b.c時且e虛繼承d:
若為多繼承時,記憶體布局如下:
虛繼承的記憶體布局如下:
第乙個vbptr 存放3個資料,因為指標合併,向距離作用域最近的指標內層合併
};當a為虛基類,虛繼承於b時且b虛繼承d
若為多繼承時,記憶體布局如下:
虛繼承的記憶體布局如下:
第乙個vbptr 存放3個資料,因為他代替的是b這個虛基類,c中的a沒有vbptr,因為c沒有虛繼承a,只有b虛繼承a,所以只有b的a可被替換成vbptr
構造順序:
先是非虛基類,後虛基類
a->c->a->b->e->d
先構造c,c裡有基類a,先構造基類a,後c,同理a,b,最後e.d
析構順序與構造順序相反
編譯期間,系統會新增乙個隱藏成員vfptr
基類指標引用指向或者引用派生類物件時,一定要將基類的析構寫成虛函式
1.虛函式和虛繼承的對比
class base
void show(){}
public:
int mb;
};class derive : virtual public base
virtual void show(){}
public:
int md;
};
多繼承記憶體布局:
虛繼承記憶體布局:
2、成為虛函式的條件:
1.要能取位址
2.依賴物件呼叫
建構函式 不可以 系統呼叫 不依賴物件呼叫
析構函式 可以
內聯函式 不可以 不能取位址 函式在呼叫點直接展開
static函式 不可以 無this指標 不依賴物件呼叫
3、虛函式表:
第一行:rttl(run time type information)執行時型別資訊
第二行:虛函式指標的偏移
第三行:虛函式的入口位址
虛表的寫入時機 建構函式的執行之前
虛函式指標和虛基類指標
上述部落格給出了以下結論 每個類都有虛指標和虛表 如果不是虛繼承,那麼子類將父類的虛指標繼承下來,並指向自身的虛表 發生在物件構造時 有多少個虛函式,虛表裡面的項就會有多少。多重繼承時,可能存在多個的基類虛表與虛指標 如果是虛繼承,那麼子類會有兩份虛指標,乙份指向自己的虛表,另乙份指向虛基表,多重繼...
虛基類 虛函式和純虛基類
首先看乙個例子 class base class child1 public base class child2 public base void main else p print 函式呼叫的時候,檢視虛表,根據p的位址首先從虛表裡面查詢要呼叫的函式 這裡呼叫child2的print 函式 ret...
虛基類 虛函式 純虛函式和抽象類
一 虛基類 在 多繼承 中講過的例子中,由類a,類b1和類b2以及類c組成了類繼承的層次結構。在該結構中,類c的物件將包含兩個類a的子物件。由於類a是派生類c兩條繼承路徑上的乙個公共基類,那麼這個公共基類將在派生類的物件中產生多個基類子物件。如果要想使這個公共基類在派生類中只產生乙個基類子物件,則必...