探索C++虚函数

探索C++虚函数

 1 测试环境

  各个编译器对虚函数的实现有各自区别,但原理大致相同。本文基于VS2008探索虚函数

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为例,构建对象模型,如下图所示:

 

  • 类对象的最前面为指向虚表的指针(4个字节
  • 虚表的每一项对应类声明的虚函数指针(4个字节),因此,获取虚表的起始地址后,可以根据偏移获取到各个虚函数地址
  • 虚函数的指针指向虚函数,只要知道虚函数的格式(声明),就可以调用对应的虚函数

4 代码调试访问虚表

  本册测试结构为

  首先创建一个类对象,通过类起始地址获取得到类的前4个字节,即虚表地址。

 

  拿到虚表地址后,查看虚表。函数指针每4个字节为1个单位,下面的虚表地址下共有3个虚函数,虚表以0结束。

 

  取得虚表的第一个函数,这里是C1::f1,地址是00 0a 10 c3,访问该地址。并将该地址转换为函数指针:

 

  调用后进入函数体

 

猜你喜欢

转载自www.cnblogs.com/hgwang/p/9649178.html