C++虚表地址和虚函数地址

虚函数是c++实现多态性的一个重要知识点,本文主要解析虚函数在内存中的地址,以及与虚表地址的关系。
声明一个类,包含两个虚函数,一个普通成员函数和一个类成员。

调试程序,查看test对象的内存分布如下:

_vptr是一个指向虚表的指针,可以理解为一个int* p[2],在本例中,p[0]是指向Test::func1()地址的指针,p[1]是指向Test::func2()地址的指针。那么可以直接通过p值来调用这两个虚函数:
*(p[0])() 输出Test::func1
*(p[1])() 输出Test::func1
而_vptr又总是存在于类内存空间的首位,可以通过对test取地址得到_vptr,然后再进行上述操作,代码验证如下:

对上述地址操作做一个简单地说明:
&test是获取到类实例对象的地址,
(intptr_t*)&test)将该地址转为整数型指针,再对其进行取值操作,得到指向指向虚函数表的指针的地址(这里不是打错字,请注意断句)。
((intptr_t)&test)是指向虚函数表的指针值,那么虚函数表的地址值就是*(intptr_t*)((intptr_t)&test),取虚函数表的地址的前4/8个字节,就是虚函数表中的第一个虚函数地址。强转为函数指针,也就是p1,从监视窗口可以看到,p1的地址确实是Test::func1()的地址。
(intptr_t*)((intptr_t)&test再进行+1操作(此处指针类型为intptr_t,那么+1就是偏移4或者8个字节),得到p2,也就是是Test::func2()的地址。
既然我们都可以取到指向虚函数表的指针,同样的我们就可以“修改”一个类对象的虚函数表,这里用引号是因为一个类的虚函数表是不能被修改的,我们只能修改指向虚函数表的指针,把它骗过去。。。代码如下:

class Base
{
public:virtual void func1() = 0;virtual void func2() = 0;
};class Test1 : public Base
{
public:virtual void func1(){std::cout << __FUNCTION__ << std::endl;}virtual void func2(){std::cout << __FUNCTION__ << std::endl;}
};class Test2 : public Base
{
public:virtual void func1(){std::cout << __FUNCTION__ << std::endl;}virtual void func2(){std::cout << __FUNCTION__ << std::endl;}
};typedef void (*FuncPtr)();int main()
{Test1 test1;Test2 test2;Base *pBase = &test1;printf("%p\n", *(intptr_t*)&test1);printf("%p\n", *(intptr_t*)*(intptr_t*)&test1);//FuncPtr p1 = (FuncPtr)(intptr_t*)(*(intptr_t*)*(intptr_t*)&test1);//FuncPtr p2 = (FuncPtr)(intptr_t*)(*((intptr_t*)*(intptr_t*)&test2 + 1));intptr_t p[] = {((intptr_t*)*(intptr_t*)&test1)[0],((intptr_t*)*(intptr_t*)&test2)[1],};*((intptr_t**)pBase) = p;pBase->func1();pBase->func2();
}

输出结果:

C++虚表地址和虚函数地址相关推荐

  1. C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址

    C++反汇编第三讲,反汇编中识别虚表指针,以及指向的虚函数地址 讲解之前,了解下什么是虚函数,什么是虚表指针,了解下语法,(也算复习了) 开发知识为了不码字了,找了一篇介绍比较好的,这里我扣过来了,当 ...

  2. c++虚函数地址的获取

    最近在做的一个项目的一个步骤找到虚函数的实际地址.这个过程中遇到的问题,让我感觉到了自己对于C++指针的理解还是不够透彻,记录一下. 概念 指针由两个空间组成 一是指针本身占有一定的空间,32位操作系 ...

  3. C++ 获取类成员虚函数地址

    1.GNU C++平台 GNU C++ 平台获取 C++ 成员虚函数地址可使用如下方法[1]^{[1]}[1]: class Base {int i; public:virtual void f1() ...

  4. 获取成员函数地址及获取函数地址

     首先我们定义一个类Ctest,类里面包含三个不同形式的成员函数,静态成员函数statFunc().动态成员函数dynFunc()和虚拟函数virtFunc().在main函数中我们利用cout标 ...

  5. C++虚函数---我的理解

    先了解一些基础知识 1.构造函数和析构函数一般是公有成员,否则该类不能实例化 2.类成员默认访问权限是private类型(strcut默认访问权限是public) 3.析构函数一般是虚函数,否则可能会 ...

  6. C++_虚继承_虚函数_纯虚函数(多继承的二义性,多态)

    基本信息 每一个类都有一个虚表,以及虚表指针; 虚表的内容是编译器决定的,虚表中用于存放虚函数的指针, 程序运行时的类型信息等; 每个多态对象都存放着一个指向当前类型的虚表的指针, 该指针在构造函数中 ...

  7. C++多态的原理(虚函数指针和虚函数表)

    C++多态的原理 (虚函数指针和虚函数表) 1.虚函数指针和虚函数表 2.继承中的虚函数表 2.1单继承中的虚函数表 2.2多继承中的虚函数表 3.多态的原理 4.总结 1.虚函数指针和虚函数表 以下 ...

  8. C++语法——详细剖析多态与虚函数

    目录 一.虚函数与多态的概念与基本使用 (一).概念 (二).基本使用 二.虚函数的底层 三.特殊的虚函数(协变) 四.多态在多继承.菱形继承与菱形虚拟继承中的使用. (一).多继承 (二).菱形继承 ...

  9. C++虚函数表实现详细解析 (附示例)

    目录 前言 运行环境 什么是虚函数 简单示例 虚函数的实现原理 虚函数表 通过虚表找到函数地址并调用 虚函数表的具体分析 无继承关系时的虚函数表 单继承但未重写虚函数时的虚函数表 单继承且重写虚函数时 ...

最新文章

  1. python 步进电机_【Applied Motion Products】伺服电机|步进电机也可以python编程啦
  2. puppet之service管理
  3. 监控USB设备插入/拔出写法2
  4. 邮件系统三功能 建金字塔防护体系
  5. windows环境里React-Native运行失败的原因之一,缺少依赖
  6. Linux下安装compsoer ,并使用composer安装laravel
  7. 计算机论文搜索技巧【一】
  8. python3 实现对比conf 文件差异
  9. 使用 guava-retrying 实现灵活的重试机制
  10. 谈谈Javascript中那些For循环的事
  11. json oracle 导入,JsonToOracle-Json导入Oracle工具下载 v2.0 官方版 - 安下载
  12. 转: JavaScript判断浏览器类型及版本
  13. 基于SSM的个人健康管理系统
  14. Protel 99se 快捷键
  15. PostgreSQL查询优化器详解(逻辑优化篇)
  16. 图像标签制作工具之labelImg-windows的安装与使用
  17. 为云而生,腾讯云服务器操作系统TencentOS内核正式开源
  18. application/octet-stream里的octet是什么意思
  19. 微信小程序使用本地背景图无法渲染的解决办法
  20. JAVA——从基础学起(五)类和对象

热门文章

  1. JZOJ·滑雪场的缆车【DP】
  2. LocalDateTime运算案例,以及参考网站
  3. sendfile函數的使用
  4. 美团外卖兼职值得干嘛,赚的多吗
  5. 吃鸡用什么蓝牙耳机好?超低延迟专业游戏蓝牙耳机推荐
  6. 国防科技大学计算机非军籍研究生就业情况,国防科大“非军籍本科生”值得报考吗?非常值得!毕业就是金饭碗...
  7. MUI-设置沉浸式状态栏后MUI导航栏的高度问题
  8. java多线程之倒计时器CountDownLatch
  9. linux ariod 的总结
  10. 想要气场强大,在气势上压倒对方,如此重要的4条,不用就亏大了