不同繼承體系下帶虛函式的物件模型

2021-08-20 05:20:30 字數 3738 閱讀 1739

單繼承

多繼承****:

class b1

virtual

void fun2()

public:

int _b1;

};class b2

virtual

void fun2()

public:

int _b2;

};class d:public b1,public b2

virtual

void fun3()

public:

int _d;

};int main()

我們先定義了兩個基類b1和b2,在這兩個基類中分別定義fun1和fun2兩個虛函式,再定義乙個派生類d公有繼承b1和b2,在d中對fun1進行重寫,並再新增乙個虛函式fun3,輸出d類物件的大小為20

通過畫圖分析我們發現派生類物件中存在兩張虛表,分別對應基類b1和b2,派生類中重寫虛函式fun1,對兩張虛表中的fun1都進行了覆蓋,在派生類中新增的虛函式fun3被加入到了先繼承的基類b1的虛表中,系統這樣做的目的是在呼叫fun3時方便查詢,只需取該物件的前四個位元組拿到虛表指標即可訪問。

當我們將基類b1中的fun1和fun2去掉virtual關鍵字,宣告為一般的成員函式,而不是虛函式,再執行該程式,發現派生類物件d的大小變成了16個位元組,還是通過畫圖我們來see一see它的物件模型:

變成了這樣乙個造型,雖然我們在派生類中先繼承b1,在繼承b2,但是系統還是將b2對應的部分放在派生類物件的最前面,原因可想而知,帶有虛函式的類中前四個位元組一般放的都是虛表指標,方便查詢虛表,因此可以認為虛基類的優先順序比一般基類的優先順序要高。

菱形繼承

在該菱形繼承中,c1將基類b中的fun1重寫,並新增加了虛函式fun3;c2將基類b中的fun2重寫,並增加了fun4,派生類d繼承c1和c2,並重寫fun1、3、4,增加fun5,因此兩張虛表都被改寫,fun5被加入第一張虛表,目的是在呼叫fun5時方便查詢。

虛擬繼承

class b

virtual

void fun2()

public:

int _b;

};class d :virtual

public b

;int main()

在基類b中我們定義了兩個虛函式fun1和fun2以及乙個成員變數_b,派生類d虛擬繼承基類b,d中只定義了乙個成員變數_d,我們知道虛擬繼承的物件模型是倒立的,基類在下,派生類在上,前四個位元組放的是偏移量表的位址,該表中前四個位元組是相對派生類物件起始位址的偏移量,後四個位元組是基類的相對該位置的偏移量,通過該錶可以找到基類在該物件中對應的位置。由於派生類d未對基類中的虛函式進行重寫,因此基類虛表無改動,對應下圖

若在派生類中對fun1重寫,並且加上虛函式fun3,其物件模型會是什麼樣嘞

class d :virtual

public b

virtual

void fun3()

public:

int _d;

};

重寫fun1後,基類b對應的虛表被改寫,該物件模型對應的前四個位元組放的也是乙個虛表的位址,在這個虛表中只有派生類中新加入的虛函式;下面四個位元組是偏移量表的位址。

菱形虛擬繼承

菱形虛擬繼承解決了菱形繼承中的二義性問題,我們接下來看一看加入虛函式後它的物件模型是怎麼樣的。

**與上面菱形繼承的**相同,只是在c1和c2類繼承基類b時加上了virtual關鍵字。

int main()

其物件模型見下圖,基類b在整個物件模型中只有乙份,並且存放在最下面,由於先繼承自c1類,因此c1類對應部分放在上面,其中前四個位元組為c1的虛表位址,派生類d對fun3重寫,因此呼叫d中的fun3,d中新新增的fun5也被放入c1的虛表中,方便查詢,接著四個位元組是偏移量表的位址,該錶前四個位元組是相對於c1所對應部分起始位置的偏移量,後四個位元組是基類b對應部分相對該位置的偏移量,再下面四個位元組存放的是c1類的成員變數_c1。c2和c1類似,基類b中前四個位元組是b對應的虛表位址,該虛表中fun1先在c1中被重寫,再在d中被重寫,fun2在c2中被重寫,最後被改寫成了下面這樣的造型

帶虛函式的各種繼承其物件模型就分析到這裡,over!

6 1 繼承體系下的物件構造步驟

include pch.h include include include include using namespace std namespace nmsp1 命名空間 virtual a virtual void myvirfunc virtual void myvirfunc2 classb...

c 實函式虛函式在繼承體系中是如何呼叫的

函式是屬於類的,不是屬於物件。我們來講函式的呼叫機制,在c 中函式分為,實函式和虛函式,他們的呼叫機制不同。先來看看類的編譯資訊,對於乙個類他的編譯資訊中含有 1.實函式,2.虛函式,這些靜態呼叫是用,由於虛函式有動態呼叫的特徵,所以虛函式存在乙個虛函式表裡,被所有的物件共享。既然虛函式資訊既在類資...

C 的類與物件 關於繼承與虛函式

今天星期五,前兩天杭州天氣不錯,但是晚上又開始下雨了,之後的幾天也要下雨,真是令人難受。ok,這個星期主要複習了關於類的繼承相關知識。1 繼承 c 允許程式設計師定義乙個基於舊類的新類,這個舊類叫做基類,新類叫做派生類。c 中類繼承的 如下 class mat 首先定義乙個基類 class mat2...