class B : public A { };
A* p1 = new B; // B may be larger than A :OK [Line 1]
B* p2 = new A; // B may be larger than A :Not OK [Line 2]
我不明白筆者在1號線和2號線
評論意味着我們爲什麼不能在2號線做?
class B
從class A
派生,它 - 從它所包含的成員變量的角度看 - 意味着它有一切有和任何它選擇將自身添加。在你簡單的代碼中,B沒有添加任何東西,但是如果它確實有其他數據成員,它顯然需要更多的內存來存儲比簡單的A
類型。如果它添加了一個虛擬成員函數,其中A沒有,那麼編譯器可能會在B中添加一個指針,該指針記錄虛擬調度表的地址,其中列出了其virtual
成員函數的地址。如果感覺像編譯器一樣,編譯器也可以自由添加填充。
因此,一般情況下派生類的大小是其基類大小的>=
。
A* p1 = new B; // B may be larger than A :OK [Line 1]
這裏,但是太多的空間B
實際需要正在從堆/空閒存儲分配,並存儲在p1
內存的地址。如果B
大於A
,則沒有區別 - 這就是其他地方 - 關鍵是B*
保證能夠存儲在A*
中。
B* p2 = new A; // B may be larger than A :Not OK [Line 2]
這裏,被在堆上創建了一個新A
,但程序員是想告訴編譯器,有一個B
在該地址。編譯器不會相信它(除非被迫) - 你只會得到編譯器時間錯誤。如果你強迫編譯器(如P2 =(B *)(新一)) to treat the memory address in
P2 as if it were an
乙, then it may later try to access additional data it expects to be part of any
乙which simply doesn't exist in any
A`:額外的數據成員,虛擬調度指針等。這裏
事實上,由於空基類優化和一些奇怪的ABI佈局,我認爲'A'可能比'B'大。 –