C++迈向精通:当我尝试修改虚函数表

尝试修改虚函数表

本期纯整活儿好吧!!!!

初衷

有一天我突然开始好奇虚函数表是否真的存在,于是我开始想是否能够从C++中查看或者调用虚函数表中的内容。,于是有了下面的操作。

操作过程

起初我并没有思路,但是我知道,每一个类对应一个虚函数表,因此首先我需要一个虚函数,因此我随便写了一个基类:

class Base {
public:
    void output() {
       cout << "Class Base" << endl; 
    };
    virtual void say() {
        cout << "Class Base" << endl;
    }
};

然后写一个子类,去 override 一下他的这个函数:

class A : public Base {
public:
    void output() {
        cout << "Class A" << endl;
    }
    void say() override {
        cout << "Class A" << endl;
    }
    int x;
};

然后按照同样的方式再创建一个 B 类:

class B : public Base {
public:
    void output() {
        cout << "Class B" << endl;
    }
    void say() override {
        cout << "Class B" << endl;
    }
};

这样以来,应该会有三个虚函数表,分别是:

  • Base基类对应的虚函数表
  • A类对应的虚函数表
  • B类对应的虚函数表

然后如何调用他们呢?我想了好久,想出这样的一个方法:

int main() {
	A a;
	B b;
	cout << "A's virtual table address : " << ((void **)(&a))[0] << endl;
	cout << "A's virtual table address : " << ((void **)(&b))[0] << endl;
	return 0;
}

根据理论来说,C++中的虚函数表应该在类内空间的第一个位置,占八个字节,是一个指向函数表的指针,那么我们就应该这样做:

((void **)(&b))[0];

这会返回一个虚函数表的地址。

这句话是什么意思呢?首先我们要清楚,对象的空间分配与结构体是一样的,而根据理论来看,虚函数表的指针会被编译器自动添加在对象空间的初始位置,也就是说,对象所在的空间的第一个单元存储的是虚函数表的地址。

如何获得这个首地址呢?首先我们要像取数组首地址一样,用取地址符号获得对象的首地址。然后将其强制转换为 (void **) 类型,这相当于让电脑将这个对象的空间看作一个数组,这个数组中存放的全部都是指向 void * 类型的数据的地址。

void * 类型是函数指针类型,我们不用管,最后在末尾添加[0]就相当于得到了虚函数表的地址。

尝试输出一下:
1
嗯,看起来没啥问题,但是如何证明他是个虚函数表的地址呢?

我能否将一个类中的修改到另一个虚函数表中?然后让这个对象执行的时候出现另外一个类的动作?

于是我开始了下面的尝试:

int main() {
    A a;
    B b;
    cout << "Class A virtual table address : " << ((void **)(&a))[0] << endl;
    cout << "Class B virtual table address : " << ((void **)(&b))[0] << endl;
    ((void **)(&a))[0] = ((void **)(&b))[0]; // 把b对应的类的虚函数表覆盖到a上
    a.say(); // 如果虚函数表被覆盖了的话,那么就会出现a执行了b的say方法的状况
    b.say();
    
    return 0;
}

然而结果是这样的:

2
发现结果并没有被改变,这是怎么回事?我百思不得其解,多方询问过之后了解到是gcc编译器把我的虚函数的调用过程给优化掉了,无奈我只能使用指针和引用来赋值:

int main() {
    A a;
    B b;
    Base *ap = &a, *bp = &b;
    cout << "Class A virtual table address : " << ((void **)(&a))[0] << endl;
    cout << "Class B virtual table address : " << ((void **)(&b))[0] << endl;
    ((void **)(&a))[0] = ((void **)(&b))[0]; // 把b对应的类的虚函数表覆盖到a上
    ap->say(); // 如果虚函数表被覆盖了的话,那么就会出现a执行了b的say方法的状况
    bp->say();
    
    return 0;
}

3
执行成功啦!!!

其实后面我还做了很多好玩的操作,这里先不放出来,写的有点累,下次再凑出一篇来!

:wq 拜拜~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/705364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

加入牛导研究团队|普通高校老师获得香港理工大学访问学者邀请函

随着国内高校高层次人才引进机制的日益完善&#xff0c;本校教师也倍感竞争压力日趋激烈&#xff0c;而出国访学&#xff0c;加入牛导的科研团队&#xff0c;发表高质量的论文&#xff0c;是提升自己学术水平的有效途径。本案例中的O老师就是借助知识人网的帮助&#xff0c;实现…

docker-compose harbor 2.11

harbor 前言 “Harbor” 是一个用于管理容器镜像的开源仓库项目。由 VMware 开发和维护,Harbor 提供一个企业级的 Docker 镜像仓库,具有丰富的功能,包括: 镜像管理:提供存储和分发 Docker 镜像的能力。安全性:支持镜像签名和漏洞扫描,确保镜像的安全性。身份认证:集成…

SECS/GEM 底层协议解析

SECS是什么&#xff1f; SEMI电子半导体联盟,为实现设备与工厂系统的快速对接数据,状态,配方,程序的标准化协议,SECS具有多个版本,本文主要介绍E5协议 HSMS通信方式,设备端的处理流程(Passive模式)。 SECS关键字 Host 主机一般指向工厂控制系统EQP 单机设备Active 在Tcp通信…

SAP 价格金额信息控制

1)migo / mb51/mb51/mb59 关于价格和金额的显示&#xff0c;需要权限控制&#xff0c;当权限对象F_BKPF_BUK,检查对应【公司代码】 和 ACTVT有03’的权限&#xff0c;如果没有03的权限&#xff0c;对应行的价格和金额显示为空 关于价格和金额的显示&#xff0c;需要权限控制&a…

Java——重载

一、重载&#xff08;Overload&#xff09; 1、重载是什么 方法重载&#xff08;Method Overloading&#xff09;是Java中实现多态的一种方式。它允许在同一个类中定义多个同名的方法&#xff0c;只要这些方法的参数列表不同。这些不同的参数列表可以通过不同的参数类型、参数…

【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版12(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言UI框架先绘制一些常用UI面板&#xff0c;设置为预制件提示弹窗用户列表菜单输入框弹窗 创建各个面板的脚本控制代码控制菜单界面按钮事件 源码结束语 前言 本节主要实现UI框架调用不同的面板界面 UI框架 不懂UI框架的设计思路…

visdom使用时所遇的问题及解决方法

最近在用visdom进行可视化的过程中&#xff0c;虽然可有效的避免主机拒绝访问&#xff08;该问题的解决方法&#xff0c;请参考深度学习可视化工具visdom使用-CSDN博客&#xff09;即在终端输入python -m visom.server 1.训练过程中visdom出现ValueError: too many file descr…

Kali之metasploit学习

目标&#xff1a;尝试使用metasploit制作一个windows 后门&#xff08;exe文件&#xff09; 一&#xff1a;使用metasploit生成一个exe安装包。 二、将对应的可执行文件放入到目标机 python3 -m http.server 端口号&#xff1a; 模块化启动一个端口。 windows 证书管理工具&…

【UIDynamic-动力学-复习昨天的内容-预习今天的内容 Objective-C语言】

一、复习昨天的内容 1.昨天我们学了,核心动画,核心动画呢,它是作用于CALayer上的,所以,我们先说了CALayer,然后,说了一个核心动画的问题, 关于这个CALayer啊,这个Layer的一些基本的属性, 1)边框:testView.layer.borderWidth = 10;// 边框是border开头儿的 2)边…

VMware安装ubuntu22.4图文教程

一 、下载镜像 下载地址&#xff1a;Index of /ubuntu-releases/22.04.4/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 二、创建虚拟机 打开VMware点击左上角文件&#xff0c;创建新的虚拟机&#xff0c;打开后如下图&#xff1a; 下一步&#xff0c;镜像文件就是…

滚动条样式

/*滚动条*/ //滚动条没有滑块的轨道部分. ::-webkit-scrollbar-track-piece {background: #fff;border-radius: 0px;opacity: 1;border: 1px solid #D9D9D9; } //整个滚动条 ::-webkit-scrollbar {width: 8px;height: 8px;background-color: transparent; } //滚动条上的滚动滑…

java.nio.charset.UnmappableCharacterException

问题 java.lang.IllegalArgumentException: java.nio.charset.UnmappableCharacterException: Input length 1 解释为编码转换有问题 问题错在位置 非汉字存在 打包的时候就会报异常

HTML列表和表格标签

目录 1.列表标签 1.1无序列表 1.2有序列表 1.3定义列表 2. 表格标签、 2.1表格标签的属性 2.2合并单元格 1.列表标签 1.1无序列表 <ul>: [type 属性&#xff1a; disc( 实心圆点 )( 默认 ) 、 circle( 空心圆圈 ) 、 square( 实心方块 )] <li>: 列表中…

C语言| 编程获取数组的长度

用sizeof也可以获得整个数组在内存中所占的字节数。 总的字节数除以一个元素所占的字节数就是数组的总长度。 这样不管数组是增加还是减少元素&#xff0c;sizeof(a) /sizeof(a[0])都能自动求出数组的长度。 字符串中有一个strlen()函数可以求出字符数组中字符串的长度。 #inc…

【python】networkx库计算:特征向量中心度

目录 0.简介 1.前提 1&#xff09;ctrl R 唤出cmd 2&#xff09;安装networkx 3&#xff09;查看networkx版本 2.方法一&#xff1a;通过给出无向图计算特征向量中心度 1&#xff09;给出无向图&#xff0c;添加节点和边 2&#xff09;可以用以下代码将无向图用pyplot…

【每日一练】day3

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

透视环世物流:一个AI降本的产业典型样本

在过去的多年时间里&#xff0c;与其说低代码完成的数字原生的普惠&#xff0c;不如说其最强的能力恰是能帮助企业用最低的门槛、最高的效率构建出与自身适配的流程和业务应用&#xff0c;在底层帮助企业构建出一个被极致拆分和分子化的软件开发中台。 而透过环世物流&#x…

Prometheus——部署详解

目录 一、Prometheus Server端安装和相关配置 1.上传安装包并解压 2.配置系统启动文件 3.启动 二、部署Node Exporters监控系统指标 三、监控Mysql配置示例 1.Mysql服务器操作 2.Prometheus服务器操作 四、监控Nginx配置示例 1.在Nginx服务器操作 2.Prometheus服务器…

Nexus搭建maven私有仓库

目录 1.Nexus介绍 2.操作步骤 1.下载Nexus 2.安装和启动nexus 3.使用私服 1.登录管理员 2.私服介绍 1.配置参数认识 2.创建仓库 4.maven使用私库 1.安装maven 2.配置maven 3.在项目中打包部署和发布 5.向私库添加jar包 ​1.添加jar 2.使用jar 1.Nexus介绍 内网…

水泥行业超低排放简介

在当今社会&#xff0c;随着环保意识的不断提高&#xff0c;水泥行业作为重要的工业领域&#xff0c;其超低排放的实施范围及成效日益受到人们的关注。朗观视觉小编将从多个角度探讨水泥行业超低排放的实施范围&#xff0c;分析其背后的意义与影响&#xff0c;展望未来的发展趋…