c 虛函式與虛表深度解析

2021-07-30 06:45:51 字數 3455 閱讀 2012

首先來看一下單繼承,編譯下面的**:

#include

#include

using

namespace

std;

class grandam

};class mother:public grandam

};class daughter :public mother

};int main()

結果如下圖所示:

第四個結果就是呼叫的是基類grandam中的虛函式。

**中:

typedef void(*introduce_self)();   //對函式進行重新命名

introduce_self* p = (introduce_self*)(*(int*)(&g)); //定義乙個函式指標,並讓它指向物件記憶體的首位址裡存放的位址(即虛表指標或位址)

(*p)(); //對虛表呼叫該函式

因為虛表裡存放的是虛函式的位址,所以對函式指標進行解引用,即就是呼叫該虛函式。

從而我們得知:

只要存在虛函式,那麼被基類指標或被基類物件引用的物件中呼叫該虛函式時,該被呼叫物件的首位址存放的是虛表指標_vfptr(位址),而虛表_vfptr中存放的是虛函式位址。
我們也可以按f10對它進行單步除錯,看記憶體中存放內容的變化,如圖所示:1. 對基類grandam物件g的函式introduce_self()呼叫時的記憶體如下圖所示:

2. 對派生類mother物件m的函式introduce_self()呼叫時的記憶體如下圖所示:

3. 對派生類mother物件m的函式introduce_self()呼叫時的記憶體如下圖所示:

4. 對派生類daughter物件d的函式introduce_self()呼叫時的記憶體如下圖所示:

1. 單繼承,**如下:

#include

#include

using

namespace

std;

class grandam

void introduce_self2()

virtual

void introduce_self3()

virtual

void introduce_self4()

};class daughter :public grandam

virtual

void introduce_self5()

virtual

void introduce_self1()

virtual

void introduce_self4()

};int main()

return

0;}

**下面這段**,是對虛表中虛函式的呼叫,注意事項如下分析:

typedef void(*intro)();

intro* pi = (intro*)

(*((int*)(&d)));

while

(*pi)

注意: 是對派生類物件d的虛表的呼叫,這是在vs 2012下執行的,因為虛表的最後乙個位址為00000000,所以可寫成此while迴圈,不同的編譯器,有不同的寫法。

執行結果如下圖:

總結我們可以看出單繼承下

按照物件位址中存放的虛表指標 :虛表裡面存放虛函式的位址順序, 去呼叫虛函式:

1).首先呼叫基類中的虛函式,按在基類中宣告的順序呼叫。

2).基類的虛函式呼叫完後,再呼叫派生類中自帶的虛函式,放在基類函式的後面。

3).呼叫派生類的虛函式時,也是按照在派生類中宣告順序呼叫的。

2.多繼承如下**:

#include

#include

using

namespace

std;

class grandam

void introduce_self2()

virtual

void introduce_self3()

virtual

void introduce_self4()

};class mother

virtual

void introduce_self2()

};class daughter :public grandam , public mother

virtual

void introduce_self5()

void introduce_self1()

virtual

void introduce_self4()

};int main()

pfun* pm1 = (pfun*)(*(int*)(&m1));

while (*pm1)

return

0;}

結果如下圖:

總結多繼承情況下,派生類自有的虛函式 在呼叫完第乙個基類的虛函式 後面呼叫。

C 虛函式與虛表

子類重新定義父類的函式重寫,但是只有父類函式宣告為虛函式的時候,才可以通過下面這種指標的方式進行呼叫,否則只能是呼叫父類的函式 include class base virtual void rewrite class derived public base void rewrite overrid...

C 深度解析 34 多型與虛函式

3 小結 前一篇部落格中我們知道,當使用父類的指標 引用 指向子類物件時,子類物件退化為父類物件,只能訪問父類中的成員。也就是說父類的指標不管指向的是父類的物件還是子類的物件,呼叫的都是父類的函式。我們希望根據實際指向的物件型別呼叫重寫函式,指標 引用 指向父類物件時呼叫父類中的成員函式,指向子類物...

虛函式與虛表

虛函式作用 c 中的多型,進行動態繫結 父類指標可指向子類的物件 直到執行時才知道要具體呼叫哪個版本 哪個類定義 的函式 它是通過虛表實現的,簡單理解如下 分析 include using namespace std class base virtual void g virtual void h ...