C++的类和new和delete和菱形继承机制
文章目录
- 参考
- 虚函数
- 使用虚函数的class结构
- 相关实现
- 源码
- IDA反编译
- 子类虚表和父类虚表
- 调用函数
- 菱形继承
参考
https://showlinkroom.me/2017/08/21/C-%E9%80%86%E5%90%91%E5%88%86%E6%9E%90/
https://www.cnblogs.com/bonelee/p/17299985.html
https://xz.aliyun.com/t/5242?time__1311=n4%2BxnD07itGQ%3DD54AKDsA3xCuU%3DwQNY4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F15779#toc-3
虚函数
在C++中,虚函数(virtual function)是一种特殊的成员函数,它允许在派生类中重写或覆盖基类中定义的函数,从而实现多态性(polymorphism)。虚函数的关键特征和用途可以概括如下:
-
声明与定义:
要声明一个虚函数,需要在基类的成员函数声明前加上virtual关键字。例如:class Base { public:virtual void someFunction() {// 基类的实现} };派生类可以重写该函数,也可以不重写,如果重写,则在派生类中提供新的实现:
class Derived : public Base { public:void someFunction() override {// 派生类的实现} }; -
虚函数表(VTable):
实现虚函数的机制通常涉及到虚函数表(Virtual Table,简称vtable)。每个含有虚函数的类都会有一个虚函数表,表中存储着该类所有虚函数的地址。每个对象都有一个指向相应类虚函数表的指针(称为vptr)。当通过基类指针或引用调用虚函数时,程序会根据对象的vptr查找到正确的虚函数表,从而调用实际对象类型的函数实现。 -
纯虚函数与抽象类:
如果基类中的虚函数没有提供实现,并且在声明时被= 0初始化,那么这个函数被称为纯虚函数。含有纯虚函数的类不能实例化,只能作为基类被继承,这样的类称为抽象类。
使用虚函数的class结构

相关实现

- new的本质,实际上就是malloc+构造函数
- delete的本质就是析构函数+free

源码
#include <iostream>
#include <string>using namespace std;class Person
{public:Person() {age = 0;name = "";};~Person() {};virtual void setName(string name) = 0;virtual void setAge(int age) = 0;
protected:int age;string name;};class Student :public Person {public:Student() {age = 17;}void setName(string name) {this->name = name;}string getName() {return this->name;}void setAge(int age) {if (age > 30 || age < 6) {cout << "not suitable for school!" << endl;return;}this->age = age;}int getAge() {return this->age;}
};int main() {Student* stu = new Student();stu->setName("Link");stu->setAge(18);cout << stu->getName() << " with age " << stu->getAge() << endl;return 0;
}
IDA反编译

子类构造函数

父类构造函数

子类虚表和父类虚表

纯虚函数的抽象类的虚表由__cxa_pure_virtual填充,有几个纯虚函数就有几个__cxa_pure_virtual,student类虚表分别有各自实现的虚函数,虚表上面是该类的typeinfo的地址

- RTTI (Run-Time Type Information) 是C++的一项特性,允许程序在运行时识别对象的类型。
typeid运算符和dynamic_cast都是基于RTTI实现的。- 每个包含虚函数的类实例,在内存中都有一个隐藏的指针(称为vptr,虚函数指针),指向该类的虚函数表(vtable)。这个vptr是在对象创建时由编译器自动初始化的。
- RTTI信息通常与vtable一起管理,其中可能包括类型描述信息和继承链信息等。
-
Aclass* ptra = new Bclass;:这行代码创建了一个指向Bclass实例的指针,但这个指针被声明为Aclass*类型。因为Bclass是Aclass的子类(假设如此),所以这是向上转型,是多态的基础。 -
int ** ptrvf = (int**)(ptra);:这里进行了一次不安全的类型转换,将Aclass指针转换为了int**。这种转换通常是为了直接访问虚函数指针(vptr),因为在许多系统上,vptr是对象内存布局的第一个元素,可以被视为一个指针的指针。但是,请注意,这种做法非常危险且非标准,违反了类型安全原则。 -
*((int*)ptrvf[0]-1):这一部分是为了找到RTTI信息的位置。ptrvf[0]访问的是第一个虚函数(按指针算起),减1则是尝试访问vptr前的一个位置,期望那里存放着RTTI相关数据的指针。这一步同样非常危险,依赖于特定编译器和平台的实现细节。 -
*((RTTICompleteObjectLocator*)(...)):这里进一步将找到的地址强制转换为RTTICompleteObjectLocator指针,并解引用它。RTTICompleteObjectLocator是一个内部使用的结构(非标准公开接口),用于存储有关对象类型的完整信息,比如类的类型描述符、偏移量到类型名称字符串等。
调用函数

对于虚函数
- 先通过对象开始八个字节得到虚表地址
- 通过虚表地址和相关偏移得到函数地址
- 调用函数
对于非虚函数 - 直接调用再text段实现的函数
菱形继承
#include<stdio.h>
#include<stdlib.h>//间接基类
class A {
public:virtual void function() {printf("A virtual function\n");}int a;
};//直接基类
class B :virtual public A { //虚继承
public:virtual void func() {printf("B virtual func()\n");}int b;
};//直接基类
class C :virtual public A { //虚继承
public:virtual void func() {printf("C virtual func()");}int c;
};//派生类
class D :public B, public C {
public:virtual void function() {printf("D virtual function()");}int d;
};int main(int argc, char** argv) {A* A_ptr = (A*)new D();A_ptr->function();return 0;
}
B和C继承A,D继承B和C
通过虚表地址减去24后的位置的内容是32,然后再加上起始地址,对应到的V4为D内的A的对象内存位置,offset vbase应该是与虚基类的偏移也就是和A的偏移


这里给各个父类对象在本对象的空间的前八个字节赋值时,用的是本对象虚表对应到的不同父类的虚函数的地址

此时对应的虚表地址,所以**两次得到D::function的地址,然后参数为对象自己

相关文章:
C++的类和new和delete和菱形继承机制
文章目录 参考虚函数使用虚函数的class结构相关实现源码IDA反编译子类虚表和父类虚表调用函数菱形继承 参考 https://showlinkroom.me/2017/08/21/C-%E9%80%86%E5%90%91%E5%88%86%E6%9E%90/ https://www.cnblogs.com/bonelee/p/17299985.html https://xz.aliyun.com/t/5242?t…...
Redis教程(二十二):Redis的过期删除和缓存淘汰策略
传送门:Redis教程汇总篇,让你从入门到精通 一、过期删除策略 Redis 中的过期删除策略是与 Redis 管理键的生命周期相关的一系列操作,用于删除过期的Key以释放内存。Redis 提供了三种主要的过期删除策略: 1、惰性删除(Lazy Expiration) 工作原理:当客户端尝试访问一个…...
Lodop 实现局域网打印
文章目录 前言一、Lodop支持打印的方式lodop 打印方式一般有3种:本地打印局域网集中打印广域网AO打印 二、集成步骤查看lodop 插件的服务端口:查看ip后端提供接口返回ip,前端动态获取最后步骤 前言 有时候会根据不同的ip来获取资源文件&…...
HarmonyOS(二十四)——Harmonyos通用事件之触摸事件
1.触摸事件。 触摸事件是HarmonyOS通用事件的一种事件之一,当手指在组件上按下、滑动、抬起时触发。 名称是否冒泡功能描述onTouch(event: (event?: TouchEvent) > void)是手指触摸动作触发该回调,event返回值见下面TouchEvent介绍。 2. TouchEve…...
2024-前端面试的正确打开方式(GitHub火爆场景题剖析)
写在前面 最近前端面试大家有没有感觉到场景题的压迫感!!! 很显然普通面试八股不会怎么更新,而且就前端来说,面试并不是真正困难的,常规八股显示不出面试者的技术水平。 前端作为一个技术行业,…...
Vue3项目炫酷实战,检测密码强度值
在前端项目开发中,确保用户密码的强度是保护账户安全的重要措施。本文将演示如何使用Vue 3实现一个简单的密码强度检测功能。通过实时反馈,帮助用户创建更安全的密码,从而提升整体系统的安全性。无论您是前端开发新手还是经验丰富的开发者&am…...
PHP实现抖音小程序用户登录获取openid
目录 第一步、抖音小程序前端使用tt.login获取code 第二步、前端拿到code传给后端 第三步、方法1 后端获取用户信息 第四步、方法2 抖音小程序拿到用户信息把用户信息传给后端 code2Session抖音小程序用户登录后端文档 第一步、抖音小程序前端使用tt.login获取code 前端 …...
Linux进程无法被kill
说明:记录一次应用进程无法被kill的错误; 场景 在一次导出MySQL数据时,使用下面的命令,将数据库数据导出为.sql文件,数据量大,导出时间长,于是我就将服务器重启了。 mysqldump -u username -…...
MySQL binlog三种模式
1.statement statement 记录的是sql语句。比如一条sql,update table_user set age 20 where id between 1 and 100。这条sql会更新100条数据,但是statement 模式下只会记录这条sql语句。 优点:不需要记录数据的变化,减少了bin …...
【CentOS 7】挑战探索:在CentOS 7上实现Python 3.9的完美部署指南
【CentOS 7】挑战探索:在CentOS 7上实现Python 3.9的完美部署指南 大家好 我是寸铁👊 总结了一篇【CentOS 7】挑战探索:在CentOS 7上实现Python 3.9的完美部署指南详细步骤✨ 喜欢的小伙伴可以点点关注 💝 前言 此篇教程只适用于p…...
oracle删除表空间和用户命令
创建表空间和用户可参考 ORACLE创建表空间,用户,修改密码,分配权限,以及导入导出_oracle表空间的密码-CSDN博客 1.删除表空间 --删除空的表空间,但是不包含物理文件 drop tablespace tablespace_name; --删除非空表空间,但是不包含物理文件 drop tabl…...
企业微信hook接口协议,ipad协议http,获取未发送群发列表
获取未发送群发列表 参数名必选类型说明uuid是String每个实例的唯一标识,根据uuid操作具体企业微信 请求示例 {"uuid":"1753cdff-0501-42fe-bb5a-2a4b9629f7fb" } 返回示例 {"data": {"listdata": [{"now_cnt&qu…...
oracle中的INTERVAL函数学习总结
Oracle 从9i数据库开始引入了一种新特性,可以用来存储时间间隔,出现了INTERVAL 函数。这个函数的表达式比较多,初学比较费劲不好掌握,经过以几个小时的查阅资料和实验,总结如下: interval year t…...
爬虫(没)入门:用 node-crawler 爬取 blog
起因 前几天想给一个项目加 eslint,记得自己曾经在博客里写过相关内容,所以来搜索。但是发现 csdn 的只能按标题,没办法搜正文,所以我没搜到自己想要的内容。 没办法只能自己又重新折腾了一通 eslint,很烦躁。迁怒于…...
GAMES104笔记
GAMES104 文章目录 GAMES10401.从入门到实践什么是游戏引擎学习顺序 02.引擎架构分层资源层功能层核心层平台层工具层总结 03.如何构建游戏世界其它需要管理的复杂情况 04.游戏引擎中的渲染实践Rendering游戏引擎中的绘制知识点(结合实际进化而来)渲染基…...
ARM功耗管理架构演进及变迁
安全之安全(security)博客目录导读 目录 一、功耗管理架构演进及变迁概述 二、多核 三、big.LITTLE 四、DynamIQ...
ARM-V9 RME(Realm Management Extension)系统架构之系统能力的设备隔离和保护
安全之安全(security)博客目录导读 目录 三、设备隔离和保护 1、外设隔离 2、非pe请求者(设备)...
如何为律师制作专业的商务名片?含电子名片二维码
律师关注细节,律师名片也不例外。它们不仅仅是身份的象征,更是律师专业形象的代表,传递专业知识和信任。今天就来和我们一起来看看制作律师商务名片的注意事项,以及如何制作商务名片上的电子名片二维码? 一、名片的主…...
方案设计|汽车轮胎数显胎压计方案
一、引言 数显轮胎胎压计是一个专门测量车辆轮胎气压的工具,它具有高精度测量的功能,能够帮助快速准确获取轮胎气压正确数值,保证轮胎使用安全。本文将对数显轮胎胎压计的方案技术进行分析,包括其基本原理、硬件构成、软件设计等方…...
MySQL学习——选项文件的使用
MySQL 的许多程序都可以从选项文件(有时也被称为配置文件)中读取启动选项。选项文件提供了一种方便的方式来指定常用的选项,这样你就不必每次运行程序时都在命令行上输入这些选项。 要确定一个程序是否读取选项文件,你可以使用 -…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
