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

news2024/11/25 0:58:01

尝试修改虚函数表

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

初衷

有一天我突然开始好奇虚函数表是否真的存在,于是我开始想是否能够从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 拜拜~~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gridview的模板按钮如何判断用户点击的是哪一行

在asp.net的 GridView 控件中&#xff0c;判断用户点击的是哪一行通常可以通过处理 GridView 的 RowCommand 事件来实现。RowCommand 事件会在 GridView 的每个按钮&#xff08;除非另有指定的CommandName&#xff09;被点击时触发&#xff0c;并且事件参数中包含了足够的信息来…

基于redis的分布式锁

一、redis分布式锁基本信息 1.详细讲解&#xff1a; Redis 分布式锁是一种用于控制分布式系统中多个进程对共享资源的并发访问的机制。通过 Redis 的原子操作和过期时间功能&#xff0c;可以实现一个简单而有效的分布式锁。接下来&#xff0c;我们将详细介绍其工作原理、基本…

杨氏矩阵和杨辉三角的空间复杂度较小的解题思路

文章目录 题目1 杨氏矩阵题目2 杨辉三角 题目1 杨氏矩阵 有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个数字是否存在。 要求&#xff1a;时间复杂度小于O(N); 思路: 我们可以通过题目…

springboot SSM 宠物医院管理系统(源码+论文)

绪论 1.1 计算机管理信息系统的发展情况 1958 年美国首先提出了 “管理信息系统 ”&#xff08;即 MIS&#xff1a;Management Information Systems&#xff09;&#xff0c;从而也引出了另外一个概念 ——“管理信息系统 ”。综合其多种定义以及根据在实际中的应用&#xff…

C语言| 数组

直接定义一个数组&#xff0c;并给所有元素赋值。 数组的下标从0开始&#xff0c;下标又表示数组的长度。 【程序代码】 #include <stdio.h> int main(void) { int a[5] {1, 2, 3, 4, 5}; int i; for(i0; i<5; i) { printf("a[%d] %d\…

HSP_08章 断点调试

P100 断点调试 1. 基本介绍 一个实际场景 在开发中&#xff0c;新手程序员在查找错误时&#xff0c;这时有经验的程序员就会提示&#xff0c;可以用断点调试&#xff0c;一步一步的看源码执行的过程, 从而发现错误所在。 断点调试介绍 -基本介绍 2. 函数的调试

在不使用js在情况下只用css实现瀑布流效果

使用到的是grid 布局&#xff0c;需要注意的是grid-template-rows: masonry; 目前只有Firefox 浏览器支持这个效果&#xff0c;而且还是一个实验性属性需要在设置里面开发实验性选项才行。 实例 <!DOCTYPE html> <html> <head><title>Document</ti…

某国资集团数据治理落地,点燃高质量发展“数字引擎”

​某国有资产经营控股集团为快速提升集团的内控管理能力和业务经营能力&#xff0c;以数字化促进企业转型的信息化建设势在必行。集团携手亿信华辰开启数据治理项目&#xff0c;在数据方面成功解决“哪里来、怎么盘、怎么管、怎么用”的问题&#xff0c;不断推动企业数字化转型…

焦化行业排放平台简介

在当今社会&#xff0c;环保事业日益受到人们的关注。焦化行业作为重要的工业领域之一&#xff0c;其排放问题一直是环保工作的重点。为了有效控制焦化行业的排放&#xff0c;实施焦化行业排放平台成为了必不可少的措施。朗观视觉小编将详细探讨焦化行业排放平台的实施范围&…

vue技巧(十)全局配置使用(打包后可修改配置文件)

1、背景 vue打包目前主流用的有webpack和vite两种&#xff0c;默认用的webpack。&#xff08;二者的区别大家可以各自上网查&#xff0c;我没用过vite&#xff0c;所以不过多介绍&#xff09;vue通过webpack打包后&#xff0c;源码会被压缩&#xff0c;但一些关键配置可…

YOLOv10在RK3588上的测试(进行中...)

1.代码源 国内镜像站在gitcode。这个镜像站也基本上包含了github上常用项目的镜像。然后它的主发布源在这里&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台 yolov10是清华主导做的... 然后&#xff0c;在维护列表里看到了这个&#xff1a; 2024年05月31日&am…

前端项目打包部署

打包 vue-cli脚手架的前端项目&#xff0c;点击npm脚本中的第二条编译命令&#xff0c;即可将项目编译&#xff0c;生成一个dist的文件夹&#xff0c;里面存放的就是编译好的前端项目文件&#xff0c;没有脚手架就在终端敲击npm run build命令编译前端项目 部署 Nginx 介绍:…

centos7 最简单方式安装xfce 4桌面环境

本快速指南将介绍如何在CentOS 7上安装Xfce桌面&#xff0c;该桌面将提供用于Linux系统的GUI。 Xfce是一个用于Unix之类的轻量级桌面环境&#xff0c;类似于操作系统&#xff0c;其目标是快速而又节省系统资源。 首先&#xff0c;我们需要配置EPEL存储库&#xff0c;因为这是…

Calibre版图验证工具调用_笔记

Siemens EDA Calibre版图验证工具调用 采用Cadence Virtuoso Layout Editor直接调用Siemens EDA Calibre工具需要进行文件设置&#xff0c; 在用户的根目录下&#xff0c;找到.cdsinit文件&#xff0c; 在文件的结尾处添加以下语句即可&#xff0c;其中&#xff0c;calibre.skl…

Kafka多维度调优

优化金字塔 应用程序层面 框架层面&#xff08;Broker层面&#xff09; JVM层面 操作系统层面 应用程序层面&#xff1a;应当优化业务代码合理使用kafka&#xff0c;合理规划主题&#xff0c;合理规划分区&#xff0c;合理设计数据结构&#xff1b; 框架层面&#xff1a;在不…

全面了解性格测试:探索你的内在世界

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 全面了解性格测试&#xff1a;探索你的内在世界 什么是性格测试&#xff1f; 定义和概念 &#x1f9e0; …

2006-2024年款别克君越维修手册和电路图资料更新

经过整理&#xff0c;2006-2024年款别克君越&#xff08;含君越混动版&#xff09;全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针…

Oracle 打开钱包 ORA-28368: cannot auto-create wallet

ORA-28368: cannot auto-create wallet 开启钱包抱错&#xff0c;看下钱包信息 SQL> select * from v$encryption_wallet;WRL_TYPE -------------------- WRL_PARAMETER -------------------------------------------------------------------------------- STATUS ------…

直播录制怎么录?(3个方法)

在数字化快速发展的今天&#xff0c;直播已经成为了一种重要的传播方式&#xff0c;无论是商业活动、教育培训&#xff0c;还是娱乐休闲&#xff0c;直播都展现出了其独特的价值。然而&#xff0c;直播的即时性也意味着一旦错过&#xff0c;就很难再次体验。这时&#xff0c;直…

RTSP/Onvif安防视频监控系统EasyNVR录像播放时间轴与设备时间对应不上的原因

视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。平台可提供视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xf…