虛表結構與虛繼承內存對象模型

最近看了下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的編譯器對於非虛繼承,父類和子類是共享虛表指針的。ide

相關文章
相關標籤/搜索