在深入研究虛函式表之前,我們先思考幾個問題:
1、虛函式表儲存在什麼地方
2、虛函式表中的內容是什麼時候確定的
3、虛函式表的指標什麼時候賦值
在windows系統下,虛函式表儲存在唯讀資料段(.rdata),也就是說虛函式表在編譯階段就已經形成了,虛函式表指標是在建構函式中賦值的。
相關解釋參考 c++虛函式表詳細解釋及例項分析
但是我還是想更加深入的探索一下虛函式表的實現機制:
測試**如下:
#include using namespace std;
class base1
base1(int i)
~base1(){}
virtual int get()
virtual void set(){}
private:
int _i;
};class base2
base2(int i)
~base2(){}
virtual int get()
virtual int get2()
virtual void set2(){}
private:
int _i;
};class sec:public base1,public base2
sec(int i, int j) :base1(i),base2(j), _j(j){}
~sec(){}
int get()
int get2()
//void set(){}
private:
int _j;
};int main()
在debug下發現 n 與p的值是相等的,但是p與q的位址是不同的。而且有意思的是在sec的虛函式表中,base1的get函式位址與base2的get函式位址其實是不一樣的,但是在執行過程中,都呼叫了sec的get函式。圖示如下:
到底是為什麼呢?
於是便想通過ida的強大的反彙編功能就可以了解一二。
以上**是main函式下的一部分片段,紅線部分是呼叫sec類的建構函式,跟進去看一下
可以看到在sec類的建構函式中,分別執行base1和base2的建構函式,然後再將base1和base2的虛函式表的位址賦值給變數s。其實,在base1和base2建構函式中也是先執行建構函式然後再將虛函式表的指標賦值,只不過被後來的虛函式表指標給覆蓋掉了。然後再看看虛函式表的情況:
帶著藍字中的問題,再看一下虛函式表的具體情況:
以下是base2的情況:
可以看到j_?get@sec@@uaehxz就是base1虛函式表中get函式的位址。說明,雖然在sec的虛函式表中,base1的get函式位址與base2的get函式位址不一樣,但是最終指向的函式位址是一致的。
深入理解虛函式
在c 中,在基類中被宣告為virtual並在在乙個或多個派生類中被重新定義的成員函式就是虛函式。基本格式如下 virtual return type func name arg 我們可以通過指向派生類的基類指標或引用來呼叫派生類中同名覆蓋的成員函式。如下 class a 究竟虛函式底層是如何實現多型...
虛函式指標深入理解
程式1 include using namespace std class base1 virtual void f void virtual void g void virtual void h void private int m length int m width class base2 v...
c 深入理解虛函式
為什麼使用虛函式?什麼是虛函式?虛函式是為了解決什麼問題?物件導向的三大特徵 封裝繼承 多型 1.普通虛函式 2.虛析構函式 3.純虛函式 4.抽象類 5.介面類 6.隱藏 vs 覆蓋 7.隱藏與覆蓋之間的關係 8.早繫結和晚繫結 9.虛函式表 靜態多型 vs 動態多型 靜態多型也叫做早繫結 cla...