C 中物件的記憶體布局(三)

2021-08-19 06:09:55 字數 2148 閱讀 6350

給出這樣的重複繼承:

(一)、直接繼承,沒有虛函式存在時,書寫如下:

class ca

;class cb:public ca

;class cc:public ca

;class cd:public cb,public: cc

;

檢視記憶體布局如下:

由於b和c都繼承了a,所以在d中重複出現了a中的成員變數,所以當試圖訪問間接基類中的成員變數時,務必要加上作用域。

當把類ca、cb、cc、cd中的函式都寫成虛函式時,依舊還是重複出現,如下圖:

(二)、虛繼承

書寫**如下:(將繼承關係改為虛繼承)

class ca

virtual void a()

virtual void aa()

virtual void aaa()

public:

int ma;

};class cb:virtual public ca

virtual void a()

virtual void bb()

virtual void bbb()

protected:

int mb;

};class cc:virtual public ca

virtual void a()

virtual void cc()

virtual void ccc()

protected:

int mc;

};class cd:public cb,public cc

virtual void a()

virtual void bb()

virtual void ccc()

virtual void d()

protected:

int md;

};

對於虛繼承,可以避免重複繼承的作用,列印其記憶體布局看看情況:

可以看到在虛繼承下,前面所說的出現兩次的成員變數和成員函式出現了一次,且都放在了記憶體布局中的最後面,那怎麼找到呢?就是從圖中看到的vbptr指標,它指向vbtable,vbtable中記錄了兩行數字,據分析,可以做出總結:

根據以上記憶體布局,做出列印:

typedef void (*function)(void);//函式指標

int main()

{ cd d(40);

long** pd=(long**)(&d);//將物件d的位址強轉成為二級指標。

現在就可以畫出記憶體布局:

總結:1、當出現重複繼承時(像這種菱形繼承),會重複出現間接基類的資料,一般為了避免重複出現,因此採用虛繼承(虛擬繼承)。

2、在虛擬繼承下,編譯器將重複出現的資料放在了這個記憶體布局的最後邊(當然有vfptr時還是依據vfptr優先順序高放),並且為了標記它,在每個直接父類的作用域下有了vbptr指標,用來指向存放重複出現資料相對的偏移的vbtable。

3、在檢視記憶體布局時,看到了下標七号存放著乙個0,也就是上面標記的vtordisp for vbase ca,為什麼是0?不知道為什麼,也沒查出結果,我猜想是為了做區分吧。

論c 中物件的記憶體布局

物件的記憶體布局就是計算物件所占用的記憶體大小,物件的大小只包含資料成員,類成員函式是執行 不屬於物件的資料成員。在不討論類的繼承,以及虛函式的時候。乙個物件的大小的計算公式一般為 物件的大小 sizeof 資料成員1 sizeof 資料成員2 sizeof 資料成員n 但是,即便在這種情況下,仍然...

C 物件的記憶體布局

一篇寫的比較好的部落格 這篇文章中主要想說以下幾個問題 1 如何通過物件獲得虛函式表中虛函式的位址 2 分幾種情況討論記憶體布局 1 單一繼承 2 多重繼承 3 重複繼承 4 鑽石虛擬繼承 為了解決重複繼承中出現問題而產生的虛擬繼承 1 虛函式主要是通過一張虛函式的位址表來實現的,簡稱v table...

C 物件的記憶體布局

記憶體布局是屬於較深層次的知識,很多問題往深了講都是不清楚記憶體布局的原理。最近讀到一本書,裡面講了一部分c 物件的記憶體布局,讓我對很多以前的問題都豁然開朗了。書上篇幅較大,我加上自己的理解總結了下。分為三部分 簡單物件,單繼承,多繼承 非靜態成員變數和虛函式是決定類大小的唯一兩個因素 非靜態成員...