博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《深度探索C++对象模型》调用虚函数
阅读量:6814 次
发布时间:2019-06-26

本文共 1579 字,大约阅读时间需要 5 分钟。

如果一个类有虚函数,那么这个类的虚函数会被放在一个虚函数表里面, 使用这个类声明的对象中,会有一个指向虚函数表的指针,当使用指向 这个对象的指针或者这个对象的引用调用一个虚函数的时候,就会从虚函数表中去 查找该函数,然后对其进行调用。

如果有如下的类:

class A {    public :        int m_a;        A() {}        ~A() {}        virtual void test() { cout << "A info : " << __LINE__ << " , " << __func__ << endl;}};class B : public A{    public :        int m_b;        B() {}        ~B() {}        virtual void test() { cout << "B info : " << __LINE__ << " , " << __func__ << endl;}};

 

那么我们显示出一个 B 类对象的内存状态, 这个类声明的对象的内存布局会是下面这样:

#ifdef __x86_64__cout << "__x86_64__" << endl;#else cout << "not 64" << endl;#endifcout << "sizeof(B) = " << sizeof(B) << endl;cout << "sizeof(int) = " << sizeof(int) << endl;B b;b.m_a = 0x01010101;b.m_b = 0x02020202;show_mem(&b, sizeof(b));

 

执行结果:

__x86_64__sizeof(B) = 16sizeof(int) = 4addrress      : 00 f8 cc fa ff 7f 00 00 memory layout : 00 0f 40 00 00 00 00 00 01 01 01 01 02 02 02 02

我们看到,拥有两个 int 成员变量的 b 对象,它占用的内存大小却不是 两个 sizeof(int) 的和 8,而是16。很明显,另外8个字节就是存放虚函数表地址 的了,因为目前使用的是64位系统,指针占用的空间是64 bit。

那么,我们现在知道了一个对象的内存布局后,就可以采取 "非法" 手段 调用一个虚函数了。比如下面这段代码:

#ifdef __x86_64__ typedef unsigned long int  POINT_SIZE;#elsetypedef int POINT_SIZE;#endiftypedef void(*Fun)();//获取对象的地址POINT_SIZE *po = (POINT_SIZE *)&b;//获取这个对象前 8 个字节的值,这个值是虚函数表的地址POINT_SIZE tbl = po[0];//把这个值转换为地址类型,也就是虚函数表的地址POINT_SIZE *ptbl = (POINT_SIZE *)tbl;int pos = 0;//虚函数表的第一表项就是第一个虚函数的函数地址,//这里将其转换为函数类型Fun pfun = (Fun)(ptbl[pos]);//调用这个函数pfun();

 

调用的结果是:

B info : 38 , test

 

说明调用了 B 类的虚函数,内存布局如下:

这样,我们使用非常规手段就可以调用一个类的虚函数了。

本文转自郝峰波博客园博客,原文链接:http://www.cnblogs.com/fengbohello/p/6261873.html,如需转载请自行联系原作者

你可能感兴趣的文章
C函数调用与栈
查看>>
SQL优化小技巧
查看>>
UVALive 4850 Installations 贪心
查看>>
JS 中刷新页面的方法
查看>>
励志帝马云是不是你的财富导师?
查看>>
力扣算法题—088合并两个有序数组
查看>>
APP和web设计区别
查看>>
三层fragment嵌套,接口回调方式
查看>>
sfcapd服务新增nfdump安装
查看>>
Node.js:DNS模块的使用
查看>>
C指针函数中的局部变量返回
查看>>
获取总页数和分页的公用方法
查看>>
【cocos2d-js官方文档】四、基础数据类型
查看>>
【IIS错误】IIS各种错误
查看>>
LeetCode题解 | 215. 数组中的第K个最大元素
查看>>
DL4NLP —— 序列标注:BiLSTM-CRF模型做基于字的中文命名实体识别
查看>>
Python图片裁剪实例代码(如头像裁剪)
查看>>
【虚拟机】oracle Virtual Box4.2.6虚拟机正在运行的过程中删除了其上的一个备份,之后虚拟机就无法使用了...
查看>>
数据库MySQL--条件查询/排序查询
查看>>
资源文件加载(Pack URI 方案)
查看>>