探索C++虛函數

探索C++虛函數

 1 測試環境

  各個編譯器對虛函數的實現有各自區別,但原理大體相同。本文基於VS2008探索虛函數ios

2 測試代碼

 1 #pragma once
 2 #include <iostream>
 3 using namespace std;
 4 class C1
 5 {
 6 public:
 7     C1()
 8     {
 9         mem1 = 1;
10         mem2 = 2;
11     }
12     virtual void f1()
13     {
14         cout << "this is C1 f1" << endl;
15     }
16     virtual void f2()
17     {
18         cout << "this is C1 f2" << endl;
19     }
20     virtual ~C1()
21     {
22         cout << "this is C1 deconstruction" << endl;
23     }
24     int mem1;
25     int mem2;
26 };
27 
28 typedef void (*Fun)(void);
29 
30 //調用虛函數
31 template<class F>
32 void CallVirtualFun(const int* p_virTableAddrPtr, const int index)
33 {
34     int funAddr = 0;            //定義函數地址數值,用int取函數地址
35     int* p_funAddr = NULL;        //真實虛函數地址
36     F fun = NULL;                //函數指針
37 
38     memcpy(&funAddr ,p_virTableAddrPtr + index, 4);        //從虛函數表中取函數地址,結果保存在funAddr
39     p_funAddr = (int*)funAddr;    //將函數地址數值轉換爲函數地址
40     fun = (F)p_funAddr;        //轉函數指針
41     fun();                        //調用函數
42 }
43 
44 void VirtualFunByOffset()
45 {
46     C1 mC1;
47     //取出類地址
48     int* p_classAddr = (int*)(&mC1);
49     //取出虛表的地址,類的前4個字節是虛表指針,首先取出虛表地址
50     int virTableAddrInt = *p_classAddr;
51     //根據虛表的地址訪問虛表,虛表每一項都是函數指針,佔有4個字節
52     int* p_virTableAddrPtr = (int*)virTableAddrInt;
53 
54     //將虛函數地址轉換爲函數指針
55     CallVirtualFun<Fun>(p_virTableAddrPtr, 0);    //調用虛函數表的第一個虛函數
56     CallVirtualFun<Fun>(p_virTableAddrPtr, 1);    //調用虛函數表的第二個虛函數
57 };

 

3 類對象

 3.1 虛函數表老是在類對象的起始位置

 

3.2 虛函數表中函數位置與聲明順序相關

   聲明虛虛構,看出虛析構函數在虛函數表中第一個位置函數

  

   將虛析構挪到末尾處聲明,看出虛析構在虛函數表末尾位置測試

 

3.3 類對象模型

   C1爲例,構建對象模型,以下圖所示:this

 

  • 類對象的最前面爲指向虛表的指針(4個字節
  • 虛表的每一項對應類聲明的虛函數指針(4個字節),所以,獲取虛表的起始地址後,能夠根據偏移獲取到各個虛函數地址
  • 虛函數的指針指向虛函數,只要知道虛函數的格式(聲明),就能夠調用對應的虛函數

4 代碼調試訪問虛表

  本冊測試結構爲spa

  首先建立一個類對象,經過類起始地址獲取獲得類的前4個字節,即虛表地址。3d

 

  拿到虛表地址後,查看虛表。函數指針每4個字節爲1個單位,下面的虛表地址下共有3個虛函數,虛表以0結束。指針

 

  取得虛表的第一個函數,這裏是C1::f1,地址是00 0a 10 c3,訪問該地址。並將該地址轉換爲函數指針:調試

 

  調用後進入函數體code

 

相關文章
相關標籤/搜索