前面提到過一般空類型的sizeof問題,見連結:
http://blog.csdn.net/capecape/article/details/77702446
經過進一步學習,發現虛拟繼承和多重繼承下空類型的sizeof的計算更有意思。以下是對《Inside C++ Object Model》中第三章的總結。
以下是基類和子類的繼承關系代碼:
class X {};
class Y:virtual public X {};
class Z:virtual public X{};
class A:public Y,public Z{};
X,Y,Z,A的繼承關系圖為:
對X,Y,Z,A求sizeof與機器有關,也與編譯器有關。
1)對于一些老式機器的編譯器
-
X為基類(base class)的空類型
内部無任何明顯資料,sizeof本來應該是0,但一個類或該類對象必須占有一定的空間(這樣每個該類對象才能有唯一位址),該空間預設為1。
-
Y,Z為X的派生類(derived class)的空類型
它們的記憶體空間包括3個部分:
1)指向虛基類的指針,占4bytes
2)本身空的,0位元組;繼承X的一位元組,占1byte
3)調整總大小為4bytes的倍數,故調整填充占3位元組
故Y,Z的sizeof都為8。 -
A多重繼承自Y,Z
它的記憶體空間包括4個部分:
1)基類Y的大小(減去因虛基類X而配置的大小),占4bytes,基類Z的大小同理
2)本身空的,0位元組;繼承共享的唯一一個X實體,1byte
3)調整總大小為4bytes的倍數,故調整填充占3位元組
故A的sizeof為12位元組。
2)對于新近的大多數編譯器(例如:Visual C++)
在現在的新編譯器下,一個空的虛基類被視為派生類最開頭的部分,也就是說沒有花費任何額外空間,這就節省了一般機器的char onebyte。也就不需要調整填充了(alignment padding)。在此模型下,Y和Z的大小都是4而不是8。
同樣,A也隻繼承Y,Z的指針部分,不需要繼承自X的1位元組實體,也不需要填充。故為8bytes。
總結:
- 虛拟繼承,會生成一個指針(4位元組)指向虛拟基類。
- 對于老式機器(編譯器),子類會繼承基類的(char onebyte)
- 對于新興編譯器,子類不會繼承基類的onebyte。