C++虛繼承內存對象模型探討

C++虛繼承內存對象模型探討

最近看了下Inside C++裏面講的對虛繼承層次的對象的內存佈局,發現在不同編譯器實現有所區別。因此,自己動手探索了一下。結果如下:

首先,說說GCC的編譯器.

它實現比較簡單,不管是否虛繼承,GCC都是將虛表指針在整個繼承關係中共享的,不共享的是指向虛基類的指針。

class A {

int a;

virtual ~A(){}

};

class B:virtual public A{

virtual ~B(){}

virtual void myfunB(){}

};

class C:virtual public A{

virtual ~C(){}

virtual void myfunC(){}

};

class D:public B,public C{

virtual ~D(){}

virtual void myfunD(){}

};

以上代碼中 sizeof(A)=8,sizeof(B)=12,sizeof(C)=12,sizeof(D)=16.

解釋: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.

解釋: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的編譯器對於非虛繼承,父類和子類是共享虛表指針的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章