1. 程式人生 > >C++物件模型之記憶體佈局(1)

C++物件模型之記憶體佈局(1)

轉載地址: https://mp.weixin.qq.com/s/LMJ4Hsa1hmued2egk9uWMQ

 

如果想學習在linux或者在linux平臺下開發,學習C/或C++是非常好的選擇.俗話說,術業有專攻,學一門技術,就儘量學得深,也可以作為行走江湖,混口飯吃的一項本領.

對於C,當初我是看了C與指標這門書,這本書講解了很多我沒有了解過的知識點,特別是指標講解的很到位.最後還設計了C執行時記憶體模型.

對於C++的學習,我看了C++ Primer之後,進階的書為深入理解C++物件模型,這本書講解了C++類在記憶體中是如何佈局以及成員函式是怎麼呼叫,有助於理解C++多型是如何實現的.總之,受益匪淺.

接下來,我將用幾篇文章聊聊C++物件模型.

 

 

無多型的物件佈局

 

單個類:

假設有以下一個類的定義:

 

如果類沒有虛擬函式,那麼class的佈局和c語言的struct佈局一樣,只有成員變數.物件記憶體佈局如圖1左所示.

繼承類

如果有一個類B繼承上面的類A,定義如下:

 

子類的建構函式是先構造父類,再構造子類,所以類B物件記憶體佈局只要在A成員之後加上B的成員即可,示意圖如圖1右所示:

(圖一)

 

多型下物件記憶體佈局

 

單個類:

首先定義一個類,帶有虛擬函式:

 

因為class A帶有虛擬函式,所以A物件的記憶體佈局就要增加一個虛擬函式表指標,它是一個指標,指向類A的虛擬函式表.物件模型如圖2上所示.深入理解C++物件模型將指標放在了物件的末尾,但是現在主流的編譯器都將指標放在了物件的首位置.

單繼承:

單繼承類的定義如下:

 

當父類有虛擬函式時,子類繼承父類的虛擬函式表,而且虛擬函式的順序是先父類的虛擬函式,再子類的虛擬函式;當父類的虛擬函式被子類重寫時,則虛擬函式表中的父類虛擬函式指標要替換為子類的虛擬函式指標,示意圖如圖2下.

(圖二)

 

例項驗證

 

為了驗證之前的物件模型是否正確,我寫了如下程式進行驗證:

 

稍微解釋下

 

  • (long*)bp,將物件的指標型別轉換為(long*)型別,用於取出虛擬函式表的地址.

  • *(long*)bp,*為取出指標指向的值.此式子即虛擬函式表的地址,也就是第一個虛擬函式的地址.

  • (long*)*(long*)bp,將虛擬函式表的地址指標轉換為(long*),用於後續迭代.

  • *(long*)*(long*)bp,*求指標值,即為第一個虛擬函式的地址,最後轉換為pfun指標.

該程式輸出結果為:

輸出順序和上述一樣.