C 深入理解虛表

2021-09-25 09:21:11 字數 1255 閱讀 1192

虛表是記錄本類中所有虛函式位址的乙個**。

如下,我們設計了乙個類,存在兩個虛函式。

class a

virtual void fun2()

};

通過a例項化a,再看看a的記憶體結構。_vfptr就是虛表!!!可以把它看成存放了void*型物件的陣列。而_vfptr的兩個成員分別代表fun1函式的指標和fun2函式的指標。這也正好驗證了虛表就是記錄本類中所有虛函式位址的乙個**。

經測試,通過如下**可以獲取虛表。

a a;

int *vptr = (int *)(*(int*)(&a));

再看記憶體監視資訊,我們發現vptr的位址和_vfptr的位址一樣,測試通過-v-

看上圖,我們發現vptr[0]的值與虛表中第乙個成員的值相等。那我麼可以通過吧vptr[0]轉換成fun1函式型別,來達到不可告人的目的。

typedef void (*fun)(void);

fun f1 = (fun)vptr[0];

f1();

呼叫後,控制台列印「a」,象徵著我們嘗試成功。同理,我們也可以通過vptr[1]來呼叫fun2函式。

通過上圖,我們很容易就可以看出,是按函式的宣告順序排列的。雖然簡單,但還是請記住了。不要一不小心呼叫了虛析構函式,程式直接崩潰。

我們再設計乙個aa類,繼承a,並且在a中實現fun1()函式。

class aa : public a

};

通過aa例項化aa,再看看aa的記憶體結構。

發現沒有,aa::fun1。我們只實現了fun1(),虛表中的fun1函式使用的是aa類中的實現,而fun2函式使用的時a類中的實現。有沒有隱隱約約嗅到動態繫結的味道?

看完本篇文章,是不是對神秘莫測的虛表有了更一步的認識。

這裡只是從記憶體層面講解了虛表,欲瞭解更加透徹,請查閱「繼承」,「動態繫結」等知識。

c 深入理解虛函式

為什麼使用虛函式?什麼是虛函式?虛函式是為了解決什麼問題?物件導向的三大特徵 封裝繼承 多型 1.普通虛函式 2.虛析構函式 3.純虛函式 4.抽象類 5.介面類 6.隱藏 vs 覆蓋 7.隱藏與覆蓋之間的關係 8.早繫結和晚繫結 9.虛函式表 靜態多型 vs 動態多型 靜態多型也叫做早繫結 cla...

c 深入理解虛函式

物件導向的三大特徵 相同物件收到不同訊息或不同物件收到相同訊息時產生的不同的動作。ifndef rect h define rect h include include using namespace std class rect 矩形類 endif shape h 如上面的 他們函式名相同,引數個...

C 深入理解虛函式

c 深入理解虛函式 1 在基類用virtual宣告成員函式為虛函式。這樣就可以在派生類中重新定義此函式,為它賦予新的功能,並能方便被呼叫。在類外定義虛函式時,不必在定義virtual 2 在派生類中重新定義此函式,要求函式名,函式型別,函式引數個數和型別全部與基類的虛函式相同,並根據派 生類的需要重...