深入理解虚函数表
来源:互联网 发布:vm虚拟机破解版 mac 编辑:程序博客网 时间:2024/06/06 18:53
在深入研究虚函数表之前,我们先思考几个问题:
1、虚函数表存储在什么地方
2、虚函数表中的内容是什么时候确定的
3、虚函数表的指针什么时候赋值
在windows系统下,虚函数表存储在只读数据段(.rdata),也就是说虚函数表在编译阶段就已经形成了,虚函数表指针是在构造函数中赋值的。
相关解释参考 C++虚函数表详细解释及实例分析
但是我还是想更加深入的探索一下虚函数表的实现机制:
测试代码如下:
#include <iostream>using namespace std;class Base1{public:Base1(){}Base1(int i){ _i = i; }~Base1(){}virtual int get(){ return _i; }virtual void set(){}private:int _i;};class Base2{public:Base2(){}Base2(int i){ _i = i; }~Base2(){}virtual int get(){ return _i; }virtual int get2(){ return _i; }virtual void set2(){}private:int _i;};class Sec:public Base1,public Base2{public:Sec(){}Sec(int i, int j) :Base1(i),Base2(j), _j(j){}~Sec(){}int get(){ return _j; }int get2(){ return _j; }//void set(){}private:int _j;};int main(){typedef int(*Fun)();Base1 b(1);Base2 b2(2);Sec s(3, 4);Base1 *p = &s;int k = p->get();Base2 *q = &s;int m = q->get();int n = (unsigned)&s;return 0;}
在Debug下发现 n 与p的值是相等的,但是p与q的地址是不同的。而且有意思的是在Sec的虚函数表中,Base1的get函数地址与Base2的get函数地址其实是不一样的,但是在运行过程中,都调用了Sec的get函数。图示如下:
到底是为什么呢?
于是便想通过ida的强大的反汇编功能就可以了解一二。
以上代码是main函数下的一部分片段,红线部分是调用Sec类的构造函数,跟进去看一下
可以看到在Sec类的构造函数中,分别执行Base1和Base2的构造函数,然后再将Base1和Base2的虚函数表的地址赋值给变量s。其实,在Base1和Base2构造函数中也是先执行构造函数然后再将虚函数表的指针赋值,只不过被后来的虚函数表指针给覆盖掉了。然后再看看虚函数表的情况:
带着蓝字中的问题,再看一下虚函数表的具体情况:
以下是Base2的情况:
可以看到j_?get@Sec@@UAEHXZ就是Base1虚函数表中get函数的地址。说明,虽然在Sec的虚函数表中,Base1的get函数地址与Base2的get函数地址不一样,但是最终指向的函数地址是一致的。
0 0
- 深入理解虚函数表
- 深入理解虚函数表
- 深入理解虚函数
- 深入理解C++虚函数表
- 虚函数指针深入理解
- 虚函数的深入理解
- 深入理解c++虚函数
- 深入理解C++虚函数
- 深入理解C++虚函数
- c++ 深入理解虚函数
- 深入理解C++重载、多态、虚函数
- 深入理解C++虚函数机制
- C++虚函数的深入理解
- C++虚函数的深入理解
- C++虚函数的深入理解
- 深入理解c++纯虚函数
- 深入理解JavaScript函数
- 深入理解sizeof()函数
- 【Java并发编程】之十一=十二-13-14-15-16-17--18-19-20-21-22-二十三
- Yii2高级模版使用composer在windows系统上安装
- HTML4与HTML5的区别
- dTree动态生成树(后台处理,简化前台操作)
- java学习笔记之代码块
- 深入理解虚函数表
- 摄像机标定
- 如何降低android应用程序的耗电量
- Flask学习-设备管理系统3:从excel表导入设备信息
- okhttp
- Tomcat探秘(4):tomcat启动过程详述
- VB.net学习笔记(二十七)线程同步上
- sevice层和dao层的简单理解
- java入门、java学习、java教程:Java程序员需要注意的五大Docker误区