c++類物件記憶體結構
首先介紹一下c++中有繼承關係的類物件記憶體的布局:在c++中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標__vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。
對於子類,最開始的記憶體資料記錄著父類物件的拷貝(包括父類虛函式表指標和成員變數)。 之後是子類自己的成員變數資料。
對於子類的子類,也是同樣的原理。但是無論繼承了多少個子類,物件中始終只有乙個虛函式表指標。
為了**c++類物件的記憶體布局,先來寫幾個類和函式
首先寫乙個基類:
class base
virtual void g()
virtual void h()
int base;
protected:
private:
};然後,我們多種不同的繼承情況來研究子類的記憶體物件結構。
1. 無虛函式集繼承
//子類1,無虛函式過載
class child1 : public base
virtual void g1()
virtual void h1()
int child1;
protected:
private:
};這個子類child1沒有繼承任何乙個基類的虛函式,因此它的虛函式表如下圖:
我們可以看出,子類的虛函式表中,先存放基類的虛函式,在存放子類自己的虛函式。
2. 有乙個虛函式繼承
//子類2,有1個虛函式過載
當子類過載了父類的虛函式,則編譯器會將子類虛函式表中對應的父類的虛函式替換成子類的函式。
3. 全部虛函式都繼承
//子類3,全部虛函式過載
4. 多重繼承
多重繼承,即類有多個父類,這種情況下的子類的記憶體結構和單一繼承有所不同。
我們可以看到,當子類繼承了多個父類,那麼子類的記憶體結構是這樣的:子類的記憶體中,順序
5. 菱形繼承
6. 單一虛擬繼承
虛擬繼承的子類的記憶體結構,和普通繼承完全不同。虛擬繼承的子類,有單獨的虛函式表, 另外也單獨儲存乙份父類的虛函式表,兩部分之間用乙個四個位元組的0x00000000來作為分界。子類的記憶體中,首先是自己的虛函式表,然後是子類的資料成員,然後是0x0,之後就是父類的虛函式表,之後是父類的資料成員。
如果子類沒有自己的虛函式,那麼子類就不會有虛函式表,但是子類資料和父類資料之間,還是需要0x0來間隔。
因此,在虛擬繼承中,子類和父類的資料,是完全間隔的,先存放子類自己的虛函式表和資料,中間以0x分界,最後儲存父類的虛函式和資料。如果子類過載了父類的虛函式,那麼則將子類記憶體中父類虛函式表的相應函式替換。
7. 菱形虛擬繼承
結論:(1) 對於基類,如果有虛函式,那麼先存放虛函式表指標,然後存放自己的資料成員;如果沒有虛函式,那麼直接存放資料成員。
(2) 對於單一繼承的類物件,先存放父類的資料拷貝(包括虛函式表指標),然後是本類的資料。
(3) 虛函式表中,先存放父類的虛函式,再存放子類的虛函式
(4) 如果過載了父類的某些虛函式,那麼新的虛函式將虛函式表中父類的這些虛函式覆蓋。
(5) 對於多重繼承,先存放第乙個父類的資料拷貝,在存放第二個父類的資料拷貝,一次類推,最後存放自己的資料成員。其中每乙個父類拷貝都包含乙個虛函式表指標。如果子類過載了某個父類的某個虛函式,那麼該將該父類虛函式表的函式覆蓋。另外,子類自己的虛函式,儲存於第乙個父類的虛函式表後邊部分。
(6) 當物件的虛函式被呼叫是,編譯器去查詢物件的虛函式表,找到該函式,然後呼叫。
c 類物件的記憶體模型
c 類物件記憶體結構 首先介紹一下c 中有繼承關係的類物件記憶體的布局 在c 中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標 vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。對於子類,最開始的記憶體資料記錄著父類物件的拷貝 包括父類虛函式表指標和成員變數 之後是子類...
c 類物件的記憶體模型
c 類物件記憶體結構 首先介紹一下c 中有繼承關係的類物件記憶體的布局 在c 中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標 vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。對於子類,最開始的記憶體資料記錄著父類物件的拷貝 包括父類虛函式表指標和成員變數 之後是子類...
類 物件的記憶體模型
原問題如下 include using namespace std class base void fun2 int main 的結果為4。這個我覺得是因為那個虛函式表裡的乙個指標佔了4個位元組 但是如果我去掉virtual 的結果為1 類中的普通成員函式佔物件的空間嗎?資料成員所佔空間的計算是否也...