C 物件模型

2021-09-24 22:41:37 字數 936 閱讀 9145

今天把c++物件模型重新溫習了一遍

總結:(1) 對於基類,如果有虛函式,那麼先存放虛函式表指標,然後存放自己的資料成員;如果沒有虛函式,那麼直接存放資料成員。

(2) 對於單一繼承的類物件,先存放父類的資料拷貝(包括虛函式表指標),然後是本類的資料。

(3) 虛函式表中,先存放父類的虛函式,再存放子類的虛函式

(4) 如果過載了父類的某些虛函式,那麼新的虛函式將虛函式表中父類的這些虛函式覆蓋。

(5) 對於多重繼承,先存放第乙個父類的資料拷貝,在存放第二個父類的資料拷貝,一次類推,最後存放自己的資料成員。其中每乙個父類拷貝都包含乙個虛函式表指標。如果子類過載了某個父類的某個虛函式,那麼該將該父類虛函式表的函式覆蓋。另外,子類自己的虛函式,儲存於第乙個父類的虛函式表後邊部分。

(6) 當物件的虛函式被呼叫是,編譯器去查詢物件的虛函式表,找到該函式,然後呼叫。

對於虛繼承 記憶體模型則不同

首先是自己的虛函式表,然後是子類的資料成員,然後是4個位元組的0x00000000,之後就是父類的虛函式表,之後是父類的資料成員。

簡單的可以把這種關係理解為 共享。

這裡又想到菱形繼承。

如果是普通繼承

d.print()

這樣一條語句會產生 二義性,原因是因為d 的記憶體模型中有2份 a 的拷貝,編譯器無法決定呼叫哪個。

可以改為

d.b::print()

d.c::print()

同理 如果出現

a* pa = (a*)&d; 

這樣的上行轉換語句,也會產生二義性。正確寫法:

a *pa = (a*)(b*)&d;

a *pa = (a*)(c*)&d;

當然 如果使用virtual 宣告為虛繼承。就省去了這些麻煩同時節省了空間。

補充一點: vtable在linux/unix 中存放在可執行檔案的唯讀資料段中(rodata)

c 物件模型

很久之前就想總結一下c 的記憶體使用機制。直到現在剛考完試之制,去實習之前,才有時間完成這事。1.程式使用記憶體區 乙個程式占用的記憶體區一般分為5種 1 全域性 靜態資料區 儲存全域性變數及靜態變數 包括全域性靜態變數和區域性靜態變數 2 常量資料區 儲存程式中的常量字串等。3 區 儲存程式的 4...

C 物件模型

很久之前就想總結一下c 的記憶體使用機制。直到現在剛考完試之制,去實習之前,才有時間完成這事。1.程式使用記憶體區 乙個程式占用的記憶體區一般分為5種 1 全域性 靜態資料區 儲存全域性變數及靜態變數 包括全域性靜態變數和區域性靜態變數 2 常量資料區 儲存程式中的常量字串等。3 區 儲存程式的 4...

C 物件模型

簡單物件模型 乙個c 物件儲存了所有指向成員的指標,而成員本身不儲存在物件中。也就是說不論資料成員還是成員函式,也不論這個是普通成員函式還是虛函式,它們都儲存在物件本身之外,同時物件儲存指向它們的指標。示意圖如右。簡單物件模型對於編譯器來說雖然極盡簡單,但同時付出的代價是空間和執行期的效率.顯而易見...