C 菱形繼承記憶體布局的探索

2021-08-25 22:07:38 字數 2420 閱讀 9123

1、

2、c++虛繼承下菱形繼承的物件記憶體布局依賴於編譯器。對於vs而言,虛繼承通過虛基類表和虛基類指標(vbptr)實現;對於g++而言,可能會有另一種實現方式。本文基於文章和文章中描述的實驗方法,在linux和g++編譯器環境下,測定了虛繼承菱形繼承生成物件的記憶體布局。

執行環境:

ubuntu16.04,g++5.4.0,64位

**:

#include 

using

namespace

std;

class b

virtual

void f()

virtual

void bf()

};class b1 : virtual

public b

virtual

void f()

virtual

void f1()

virtual

void bf1()

};class b2 : virtual

public b

virtual

void f()

virtual

void f2()

virtual

void bf2()

};class d : public b1, public b2

virtual

void f()

virtual

void f1()

virtual

void f2()

virtual

void df()

};int main(void)

程式執行結果:
d::f()

sizeof(t): 56

實驗步驟:

1、依次將**中處的vfptr偏移值+1,可測出vfptr指向的虛函式表的所有函式資訊;

2、變換處指標p的型別,改為d、b1、b2和b,重複1步驟,可測得所有的虛函式表中函式資訊。

結論:上述實驗中,d物件記憶體模型為:

經過記憶體補齊計算,在64位環境中d物件記憶體位56byte,與上述記憶體布局吻合。

1、派生類物件建立過程中,首先建立直接基類(非virtual繼承)的物件模型。直接基類物件建立過程可不考慮派生類因素,按照其自身的建立方法建立,依次向上。

2、建立虛基類時候,同樣不用考慮派生類,按照自身原本的方法建立。此部分記憶體放在派生類物件記憶體最後。

3、建立派生類,類中的虛函式更新到基類的虛函式表中。新新增的部分放在第乙個直接基類虛函式表最後,如上述實驗。

4、上述實驗中,b1* p = &d、b2* p = &d和b* p = &d不相同,但各自指向各自部分的虛函式表首位址。b1* p = &d和d* p = &d相同。

**1:

#include 

using

namespace

std;

class a ;

class b : virtual

public a

};int main()

不同環境下有不同結果。

測試建構函式執行順序

**:

#include 

using namespace std;

class test

test(int m)

};class a

private:

test t1;

};class b

private:

test t2;

};class c :virtual

public a, public b

private:

test t3;

};int main()

**:

#include 

using

namespace

std;

class a

};class b :virtual

public a

virtual

void fun2()

};int main()

結果:

1、linux,64位,g++:

32 2、windows,64位

40結論:驗證了之前的假設,因為windows處理虛繼承,採用虛基類表方式(vbptr),而linux無論類中有沒有虛函式,只要虛繼承,都會建立乙個虛函式表。

其實有更好的方式來直觀了解windows和linux中類物件的記憶體布局,各自系統中有相關方法,下次總結。

C 菱形繼承

在c 繼承體系中,有一類問題是永遠跑不掉的即菱形繼承問題。此類問題又被稱作鑽石繼承問題,只是一種較差的設計結構,剛好看到這個問題,特此總結一下。先來看一下菱形繼承的基本結構 a和b從基類base中繼承,而d多重繼承於a,b。那就意味著d中會有base中的兩個拷貝。因為成員函式不體現在類的記憶體大小上...

c 菱形繼承

單繼承 乙個子類只有乙個父類時稱為單繼承 多繼承 乙個子類有兩個或者兩個以上時這個繼承關係為多繼承 菱形繼承是多繼承的一種特殊情況 在繼承中子類會繼承父類的所有的成員,可以看出菱形繼承有資料冗餘和二義性的問題。assistant中會有person的兩份資料。可以從上面看出來我們的assistant中...

C 菱形繼承

1 多重繼承的問題 在c 類的繼承中會遇到這樣乙個問題,乙個派生類有兩個或者兩個以上的基類,如同下面這種繼承情況 類c繼承了類a和類b,但是類a和類b裡面有著相同的成員變數,那麼類c在使用這個成員變數的時候就會出現二義性的問題,需要通過域成員運算子進行區分 class a a void displa...