深入分析C 虛函式表

2021-09-07 16:32:44 字數 2164 閱讀 5675

c++中的虛函式(virtual function)是用來實現動態多型性的,指的是當基類指標指向其派生類例項時,可以用基類指標呼叫派生類中的成員函式。如果基類指標指向不同的派生類,則它呼叫同乙個函式就可以實現不同的邏輯,這種機制可以讓基類指標有「多種形態」,它的實現依賴於虛函式表。虛函式表(virtual table)是指在每個包含虛函式的類中都存在著乙個函式位址的陣列。本文將詳細介紹虛函式表的實現及其記憶體布局。

首先我們要知道虛函式表的位址總是存在於物件例項中最前面的位置,其後依次是物件例項的成員。下圖中vtptr就是虛函式表的位址,可看出虛函式表中的每個成員都對應類中的乙個虛函式的位址。據圖所述,我們可以使用物件例項的位址來得到虛函式表的位址,進而獲得具體的虛函式的位址,然後進行呼叫。

假如有如下定義base b;那麼虛函式表的位址vtptr的值就是:(int*)*(int*)&b,第乙個虛函式vfunc1的位址就是:*(int*)*(int*)&b,vfunc2的位址是:*( (int*)*(int*)&b + 1 ),詳見本節後文所附**。

下文為驗證**,其中base類包含3個虛函式vfunc1~vfunc3和兩個資料成員m_imem1, m_imem2,該類與上圖中的保持一致。在main中,詳細描述了怎麼獲取虛表的位址,怎麼獲取成員變數,怎麼通過虛表位址獲取虛函式的位址

class base

virtual void vfunc1()

virtual void vfunc2()

virtual void vfunc3()

private:

int m_imem1;

int m_imem2;

};int _tmain(int argc, _tchar* ar**)

程式執行結果如下面兩幅圖所示,其中左邊部分是程式執行結果,右邊部分為除錯視窗中顯示的類中各成員的值,可以發現兩者結果一致。同時在執行結果視窗中可見直接使用位址呼叫虛函式的方法也是正確的,這就驗證了我們本節開始部分的闡述。

2.1 派生類未覆蓋基類虛函式

其對應的**如下所示:

class derived : public base

virtual void vdfunc1()

void dfunc1()

private:

int m_idmem1;

};int _tmain(int argc, _tchar* ar**)

其輸出結果如下圖所示,可見與本節開始介紹的結論是一致的。

2.2 派生類覆蓋基類虛函式

**如下所示,注意這裡只給出了類的定義,main函式的測試**與上節一樣:

class devired : public base

public:

devired(int mem = 3) : m_idmem1(mem)

virtual void vdfunc1()

void dfunc1()

private:

int m_idmem1;

};

執行結果如下所示:

3.1 無虛函式覆蓋

class base2

virtual void vbase2func1()

virtual void vbase2func2()

private:

int m_ibase2mem;

};class base3

virtual void vbase3func1()

virtual void vbase3func2()

private:

int m_ibase3mem;

};class devired: public base, public base2, public base3

virtual void vdfunc1()

private:

int m_imem1;

};int _tmain(int argc, _tchar* ar**)

除錯輸出如下圖,這裡的展示結果與本節開始所展示的記憶體布局圖是一致的

3.2 有虛函式覆蓋

本節不再給出任何分析,讀者如果想徹底搞明白可以根據本文上述內容自行畫圖寫**驗證。

虛函式表分析

project100.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include pch.h include using namespace std 父類 class base virtual voidg virtual voidh class derive public bas...

C 虛函式表例項分析

多型是c 物件導向程式設計的乙個重要特性。以前看到虛函式覺得很神奇,為什麼就能實現多型了呢。最初的時候曾設想,要實現執行時多型,應該讓物件的某個部分始終指向乙個固定的位址,子類繼承的時候,就修改這個位址的內容。這樣,父類和子類都是到同乙個固定位址去讀取內容,在執行時就能表現不同行為。在看了 深度探索...

深入理解虛函式表

在深入研究虛函式表之前,我們先思考幾個問題 1 虛函式表儲存在什麼地方 2 虛函式表中的內容是什麼時候確定的 3 虛函式表的指標什麼時候賦值 在windows系統下,虛函式表儲存在唯讀資料段 rdata 也就是說虛函式表在編譯階段就已經形成了,虛函式表指標是在建構函式中賦值的。相關解釋參考 c 虛函...