天天看點

虛拟繼承下空類型的sizeof問題

前面提到過一般空類型的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的繼承關系圖為:

虛拟繼承下空類型的sizeof問題

對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位元組

    虛拟繼承下空類型的sizeof問題
    故Y,Z的sizeof都為8。
  • A多重繼承自Y,Z

    它的記憶體空間包括4個部分:

    1)基類Y的大小(減去因虛基類X而配置的大小),占4bytes,基類Z的大小同理

    2)本身空的,0位元組;繼承共享的唯一一個X實體,1byte

    3)調整總大小為4bytes的倍數,故調整填充占3位元組

    虛拟繼承下空類型的sizeof問題

故A的sizeof為12位元組。

2)對于新近的大多數編譯器(例如:Visual C++)

在現在的新編譯器下,一個空的虛基類被視為派生類最開頭的部分,也就是說沒有花費任何額外空間,這就節省了一般機器的char onebyte。也就不需要調整填充了(alignment padding)。在此模型下,Y和Z的大小都是4而不是8。

同樣,A也隻繼承Y,Z的指針部分,不需要繼承自X的1位元組實體,也不需要填充。故為8bytes。

虛拟繼承下空類型的sizeof問題

總結:

  1. 虛拟繼承,會生成一個指針(4位元組)指向虛拟基類。
  2. 對于老式機器(編譯器),子類會繼承基類的(char onebyte)
  3. 對于新興編譯器,子類不會繼承基類的onebyte。

繼續閱讀