C 物件在記憶體中的分布

2021-07-03 15:47:17 字數 2595 閱讀 8029

c++通過class的pointers和references來支援多型,這種程式風格就成為「物件導向」。

一、c++對多型的支援的三種方式

1.把乙個派生類指標隱式轉換成乙個基類指標

ex: shape *ps = new circle();

2.經由virtual function機制

ex: ps->rotate();

2.經由dynamic_cast 和typeid運算子

ex:if(circle *pc = dynamic_cast(ps))

二、class object的大小包含三個部分

1.nonstatic data members的總和大小

2.位元組對齊產生的大小

3.對virtual機制的支援產生的額外負擔

三、示例

base class

#include using namespace std;

class zooanimal

;

derived class

#include "zooanimal.h"

class bear : public zooanimal

; dances dances_known;

int cell_bolock;

};

測試函式:

#include "bear.h"

#include "zooanimal.h"

int main(int argc, char* argv)

在記憶體中的布局:

分析:sizeof(zooanimal):__vfptr(4)+loc(4)+npos(4)+__ptr(4)+_len(4)+_res(4)=24個位元組

sizeof(bear):sizeof(zooanimal)+dances_known(4)+cell_bolock(4) = 32位元組

data語意學

c++的非static 成員變數在記憶體中的儲存之所以要進行邊界對齊,原因之一是考慮了需要避免在派生類之間複製的時候產生意向之外的記憶體覆蓋,而進行邊界對齊,就可以避免這個問題。

為了拓展性,可以在基類中提供乙個virtual function介面。(只不過這樣的話,每乙個derived class將會繼承乙個基類的vptr member,多乙個virtual table,此外virtual member function的呼叫也會變得複雜,因此需要權衡)。

繼承的這個虛函式表指標在vc6裡面是放在整個記憶體塊的前端的。因為這對於「在多重繼承下,通過class members 的指標呼叫virtual function,會帶來好處,因為不用找這個指標。而放在後端則是在派生的時候可以與c語言的struct結構體進行相容,這也是需要權衡的(不過這點好像和我們程式猿沒什麼事)」

虛擬繼承和繼承多個虛擬基類是不一樣的,這個一定要明白虛擬繼承的概念,很多最頂層基類只需要保持乙份的情況下可以採用虛擬繼承機制來實現。

不過這裡有乙個問題是,採用虛擬機制來控制的派生體系,每乙個派生類都會揹負乙個基類的指標,並且是逐級向上訪問,因此當繼承層數過多的時候,就會產生效率問題。

function語意學

成員函式和非成員函式都會被編譯器進行name mangling轉換成相同的形式

因為static member functions沒有this指標這個特性。

所以不能夠直接訪問其class的nonstatic members---->要借助於具體物件

所以不能宣告為const volatile virtual--->沒有必要

所以不需要經由類物件來呼叫--->不依賴於類物件

virtual member function

對這樣乙個對虛函式z的呼叫:

ptr->z()

為了達到在執行期呼叫正確z()實體的目的,我們需要知道兩件事

1.ptr的真實型別

2.z()實體的位置

在單繼承下,virtual member function機制下,每乙個object都會有乙個vptr指向虛函式表,虛函式表中存放的就是物件的虛函式的函式實體,pure virtual funtion會占用乙個slot,但pure virtual class 的派生類中,因為這個pure virtual function不存在,所以這個slot會用來放置其他virtual function

nonvirtual function的呼叫需要繫結到具體的class object物件上,這是因為nonvirtual function與物件無關的特性,會導致取到nonvirtual function的返回值是其在記憶體中的位址,而不是乙個函式指標。(因此不能呼叫乙個函式位址,也就需要繫結到具體物件上,將這個返回的記憶體位址轉換成物件的函式指標了)

將被共享的資料放在base class中是一種正當的設計,但需要對這個成員初始化(在基類中提供帶單數的 protected constructor,或是在每乙個建構函式中初始化它)

C語言在記憶體中的分布

2019獨角獸企業重金招聘python工程師標準 先認識記憶體中的幾個區,下面的區都在記憶體中,意味著掉電會丟失。但是這不意味著記憶體條裡面真的是這樣,包括作業系統的分頁都只是對記憶體的一種管理方式,或者說是虛擬的邏輯管理。堆區和棧區屬於動態區域,其他的屬於靜態區域,為什麼這麼說?來看看他們生成的過...

類與物件在記憶體中的分布情況

人類名 person 屬性 成員變數 例項變數 體重 年齡 行為 方法 走路 吃 import 1.類的宣告 成員變數 方法的宣告 inte ce person nsobject 也不能新增static修飾 void walk void eat end 乙個類的宣告對應乙個end,中間不能巢狀別的類...

程式在記憶體中的分布

在現代的作業系統中,當我們說到記憶體,往往需要分兩部分來講 物理記憶體和虛擬記憶體。從硬體上講,虛擬空間是cpu內部的定址空間,位於mmu之前,物理空間是匯流排上的定址空間,是經過mmu轉換之後的空間。一般我們所說的程式在記憶體中的分布指的就是程式在虛擬記憶體中的儲存方式。從低位址到高位址,可分為下...