最近看了下inside c++裡面講的對虛繼承層次的物件的記憶體布局,發現在不同編譯器實現有所區別。因此,自己動手探索了一下。結果如下:
首先,說說gcc的編譯器.
它實現比較簡單,不管是否虛繼承,gcc都是將虛表指標在整個繼承關係中共享的,不共享的是指向虛基類的指標。
#include using namespace std;
class a
};class b:virtual public a
virtual void myfunb(){}
};class c:virtual public a
virtual void myfunc(){}
};class d:public b,public c
virtual void myfund(){}
};int main()
以上**中 sizeof(a)=8,sizeof(b)=12,sizeof(c)=12,sizeof(d)=16.(gcc結果)
解釋
:a中int+虛表指標。b,c中由於是虛繼承因此大小為a+指向虛基類的指標,b,c雖然加入了自己的虛函式,但是虛表指標是和基類共享的,因此不會有自己的虛表指標。d由於b,c都是虛繼承,因此d只包含乙個a的副本,於是d大小就等於a+b中的指向虛基類的指標+c中的指向虛基類的指標。
如果b,c不是虛繼承,而是普通繼承的話,那麼a,b,c的大小都是8(沒有指向虛基類的指標了),而d由於不是虛繼承,因此包含兩個a副本,大小為16. 注意此時雖然d的大小和虛繼承一樣,但是記憶體布局卻不同。
然後來看看vc的編譯器
vc對虛表指標的處理比gcc複雜,它根據是否為虛繼承來判斷是否在繼承關係中共享虛表指標,而對指向虛基類的指標和gcc一樣是不共享,當然也不可能共享。
**同上。
執行結果將會是sizeof(a)=8,sizeof(b)=16,sizeof(c)=16,sizeof(d)=24.(vc結果)
解釋
:a中依然是int+虛表指標。b,c中由於是虛繼承因此虛表指標不共享,由於b,c加入了自己的虛函式,所以b,c分別自己維護乙個虛表指標,它指向自己的虛函式。(注意:只有子類有新的虛函式時,編譯器才會在子類中新增虛表指標)因此b,c大小為a+自己的虛表指標+指向虛基類的指標。d由於b,c都是虛繼承,因此d只包含乙個a的副本,同時d是從b,c普通繼承的,而不是虛繼承的,因此沒有自己的虛表指標。於是d大小就等於a+b的虛表指標+c的虛表指標+b中的指向虛基類的指標+c中的指向虛基類的指標。
同樣,如果去掉虛繼承,結果將和gcc結果一樣,a,b,c都是8,d為16,原因就是vc的編譯器對於非虛繼承,父類和子類是共享虛表指標的。
物件記憶體模型(虛函式,虛函式表,虛指標)
從例子入手,考察如下帶有虛函式的類的物件記憶體模型 1 class a 11 12 class b a 20 21 class c b 注 在子類中出現與父類相同名稱的變數和非虛函式不是最佳實踐,這裡是為了說明其記憶體結構。其物件記憶體結構見下圖。於侯捷老師 對其分析如下 1.每個含有虛函式的類在記...
虛繼承 虛表 虛指標
c 實現多型的方法 其實很多人都知道,虛函式在c 中的實現機制就是用虛表和虛指標,但是具體是怎樣的呢?從more effecive c 其中一篇文章裡面可以知道 是每個類用了乙個虛表,每個類的物件用了乙個虛指標。具體的用法如下 class a class b public a a,b的實現省略 因為...
C 繼承,虛繼承 記憶體結構 詳解
目錄 class test1 private int num1 class test2 public test1 private int num2 void main test2記憶體結構 檢視記憶體發現父類在子類的上面 在原有的 基礎上增加了test3類 test3類繼承了 test2和test1...