程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++虛函數表解析 [二]

C++虛函數表解析 [二]

編輯:C++入門知識

 

虛函數(Virtual Function)是通過一張虛函數表(Virtual Table)來實現的。在這個表中,主要是一個類的虛函數的地址,這張表解決了繼承、覆蓋的問題,其內容真實反映了實際函數。這樣,在有虛函數的類的實例中虛函數表被分配在實例的內存中,所以,當用父類的指針從操作一個子類的時候,這張虛函數表就顯得尤為重要了,它就像一張地圖,指明了實際所應該調用的函數。

 

在C++的標准規格說明書中寫道,編譯器必須保證虛函數表的指針存在於對象實例中最前面的位置(這是為了保證正確取到虛函數的偏移量)。這意味著通過對象實例的地址可以得到虛函數表,然後可以遍歷其中的函數指針,並調用相應的函數了。請看下面的代碼

 

class Base{ 

public: 

    virtual void fun1(){cout<<"Base::fun1"<<endl;} 

    virtual void fun2(){cout<<"Base::fun2"<<endl;} 

    virtual void fun3(){cout<<"Base::fun3"<<endl;} 

private: 

    int num1; 

    int num2;  

 

}; 

typedef void(*Fun)(void); 

int main(int argc, char* argv[]) 

   Base b; 

   Fun pFun; 

   pFun=(Fun)*((int*)*(int*)(&b)+0); 

   pFun(); 

   pFun=(Fun)*((int*)*(int*)(&b)+1); 

   pFun(); 

   pFun=(Fun)*((int*)*(int*)(&b)+2); 

   pFun(); 

   return 0; 

上面程序的執行結果如下:

 

 

 

 

Base::fun1

 

Base::fun2

 

Base::fun3

 

 

可以看到通過函數指針pFun的調用,分別執行了對象b的3個虛函數。通過這個示例發現,可以強行把&b轉成int*,取得虛函數表的地址,然後再次取址就可以得到第一個虛函數的地址了,也就是Base::fun1()。如果調用Base::fun2()和Base::fun3(),只需要把&b先加上數組元素的偏移,後面的步驟類似。

 

程序中Base對象b的內存結構圖,如下圖所示:

\

 

摘自:日新為道的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved