C 虛函式表指標分析,及多重繼承虛函式表的分布

2021-10-06 20:35:04 字數 2427 閱讀 5798

c++如果想滿足動態繫結, 及基類指標或引用呼叫派生類函式,需要滿足三個條件:

1. 基類存在虛函式

2. 基類指標或引用指向派生類物件

3. 派生類需要重寫基類的虛函式

此時 a* p 指標會指向 b類物件 記憶體布局中的 a類的基類子物件 ,從而找到vptr(虛函式表指標),接著找到b類中的虛函式表,由於b類中並未重寫a類虛函式,所以使用 a*p 指標呼叫func函式會呼叫到 a::func

如果 b 類重寫了,基類a中的虛函式,那麼b類的虛函式表中對應的func函式的位址就會被改為&b::func ,所以此時用 a *p 指標呼叫func函式 , 就會呼叫到 b::func , 呼叫流程大概是:

p指標先指向了a類的基類子物件 -> 接著找到了vptr指標 -> 接著找到b類中的虛函式表 -> 呼叫func函式

需要注意的有以下幾點:

1.如果是單繼承,派生類中僅含有乙個vptr(虛函式表指標),該指標繼承與基類

2.每個類僅有乙個虛函式表(如果是多繼承的話為多個),派生類的虛 函式表中的資料(也就是函式位址),複製於基類的虛函式表,如果派生類中重寫了基類虛函式,那麼該派生類的虛函式表中對應的基類虛函式位址,會更改為派生類重寫後的函式位址,也就是派生類的函式位址

3.基類和派生類的虛函式表不是同乙個,每個類有屬於自己的虛函式表,派生類虛函式表只是複製於基類

下面討論多繼承的情況下,虛函表是怎樣生成的

此時 c 類有兩個基類 a和b , 所以 c 類中有兩個vptr, 這兩個vptr分別指向兩個虛函式表, 這兩個虛函式表都屬於c類 , 其中的資料分別複製與 a 和 b 的虛函式表 , 如果此時使用 a* a_p 指標呼叫funca函式,由於c類中並未重寫該虛函式,已導致虛函式表中的位址還是&a::funca, 所以會呼叫到 a::func, 如果使用b*b_p指標呼叫funcb函式也是如此 , 他們都會指向c類物件記憶體布局中屬於該指標型別的基類子物件,從而找到vptr,呼叫虛函式表中對應的函式,

如果c類重寫了虛函式,那麼重寫了哪乙個基類的虛函式,則該基類子物件內的vptr指標指向的虛函式表中的函式位址就會改變為重寫後的函式位址, 以下就不各個列舉了

還有一種情況就是,如果c類自身擁有虛函式,那麼會生成乙個新的虛函式表麼,答案是不會的,如果c類自身擁有虛函式的話,那麼這個函式位址會被新增到複製基類的虛函表最後乙個位置中,如果是多繼承的情況下,會被新增到繼承順序最先繼承的基類虛函式表中

如果有小夥伴想測試我上述所說的結論,但是不知道怎麼測試的話,下面這個範例供參考

class a

int a;

};typedef void (*func_p)(void);

int main()

需要注意的有以下幾點

1.如果用基類指標指向了派生類物件,並不是指向了該派生類物件的首位址,而是會指向該派生類中基類子物件的首位址

2.多繼承情況下,會按繼承順序生成基類子物件,如果是上述例子中也就是先生成a後生成b,最後生成c類自己的成員

3.一般情況下vptr指標會在基類子物件的類成員上方,(有一種解釋是為了效率,不用進行偏移就可以找到vptr指標從而找到虛函式表)

4.如果基類虛函式中引數含有預設值(預設值),這個預設值並不會實現多型,即便呼叫了派生類函式,但是這個預設值還是來自於基類函式,(為了執行的效率,預設值並不實現多型),這裡就不測試了

5. 以上所有測試結論來自於我本身所用的環境 vs2019 32位 環境下 ,各各編譯器實現不一定相同,這裡不做多的**了

多重繼承虛函式表分析

project100.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include pch.h include using namespace std 基類1 class base1 virtual voidg 基類2 class base2 virtual voidi 子類 cl...

多重繼承與虛函式表

from 一 多重繼承 1 include iostream using namespace std class b1void f1 class b2void f2 class b3void f3 class d public b1,public b2,public b3virtual void v...

虛函式表指標,虛函式表

對c 了解的人都應該知道虛函式 virtual function 是通過一張虛函式表 virtual table 來實現的。簡稱為v table。在這個表中,主是要乙個類的虛函式的位址表,這張表解決了繼承 覆蓋的問題,保證其容真實反應實際的函式。這樣,在有虛函式的類的例項中這個表被分配在了 這個例項...