首先來看一下單繼承,編譯下面的**:
#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.多繼承如下**:2).基類的虛函式呼叫完後,再呼叫派生類中自帶的虛函式,放在基類函式的後面。
3).呼叫派生類的虛函式時,也是按照在派生類中宣告順序呼叫的。
#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 ...