虚函数 虚表指针

虚函数表和虚表指针


1,虚函数的含义
用virtual声明类的成员函数称之为虚函数

2,作用
用于实现多态

存在继承关系,子类继承父类
子类重写了父类的virtual function
子类以父类的指针或者引用的身份出现
3,虚函数的实现原理
其中的关键就是两点:

虚函数表指针
虚函数表
想要理解其中的结构,还是要从内存布局看起

下面都是用debug的方式,查看其中的布局大小

一定要理解下面的四段代码

1,普通类的内存布局

代码:

因为普通函数并不占内存,所以此时对象a的并不显示内存

2,虚函数类的内存布局

代码:

此时因为类内定义了虚函数,所以就有了一个虚函数指针:_vfptr

这个函数指针指向的即为虚函数表,表内是两个虚函数的地址

3,子类不重写父类虚函数的内存布局

代码:

此时子类继承了父类的虚函数,但是没有重写,因此子类的虚函数指针指向的表中依然存放的父类的虚函数,因此也可以看到,里面的地址都是一样的

4,子类重写父类虚函数的内存布局

代码:

这个局部变量中可以看到,重写的函数虚函数表中的地址变了,没重写的函数,在虚函数表中的地址依然没变。

上面四幅图看懂就大概知道了虚函数表指针和虚函数表的关系了。

即当类中有虚函数时,就会自动产生一个虚函数表指针,这个指针指向一个虚函数表,表中就存放类中定义的虚函数

总结:

1,虚函数表指针

什么是虚函数表指针,他在哪里,有什么用?
       我们把对象首地址开始的4个字节或8个字节,这个位置我们称之为虚函数表指针(可以添加点属性看看位置)。它里面包含一个地址指向的就是虚函数表的地址

2,虚函数表

什么是虚函数表,他又在哪里,有什么用
        虚函数表里面是一组地址的数组(函数指针数组),他所在的位置就是虚函数表指针里面所存储的地址,它里面所包含的地址就是我们重写了父类的虚函数的地址(没有重写父类的虚函数那么默认的就是父类的函数地址)
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

每个包含了虚函数的类都包含一个虚表,虚表是属于类的,而不是属于某个具体的对象,一个类只需要一个虚表即可。同一个类的所有对象都使用同一个虚表 (非多重继承语境下)。为了指定对象的虚表,对象内部包含一个(唯一的)虚表的指针,来指向自己所使用的虚表。如果对比2个类,一个拥有虚函数而一个没有,那么前者的实例应该会比后者的实例多出一个指针的大小,下面验证一下:

88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

父类中如果存在虚函数,类中会隐含一个虚函数指针,指向一个虚函数表,表中存储了父类的所有虚函数入口地址。子类继承父类,会复制一份虚指针和虚表。此时如果子类重写了父类的虚函数,会将重写的虚函数入口地址更新到虚表中。若父类指针指向了子类,并且调用虚函数,会在我们更新的虚表里找虚函数入口地址,此时已经是子类重写的虚函数了。

77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777

虚函数实现原理:

一个含有虚函数的类都有至少一个虚函数表,里面存放着该类所有虚函数的指针。

类的所有对象都共享类的虚函数表,这些对象都有一个或多个虚函数表指针来指向一个或多个虚函数表。

子类继承父类时也会继承父类的虚函数表,但父类的虚函数表和子类继承过来的虚函数表是两个独立的表。

当子类重写父类中虚函数的时候,会用重写后函数的指针代替继承过来的虚函数表中的原函数指针。

当使用父类类型的指针指向一个父类或子类对象,并调用其虚函数,会在程序运行时根据指向的对象是父类还是子类对象来决定调用的是父类中的虚函数还是子类重写的虚函数,称为动态多态。具体实现原理:当用父类指针指向子类对象时会进行指针转换,使得父类指针指向子类对象中的父类部分,通过指针调用指向对象的虚函数时,会通过指向对象中起始位置的虚函数表指针找到虚函数表,经过一定的偏移量找到对应的虚函数指针。
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666


 

在C++中,虚函数是一种特殊的函数,它可以被子类覆盖或继承。为了实现虚函数的动态绑定,C++编译器使用了虚函数表(Virtual Function Table,VTable)和虚函数表指针(Virtual Function Table Pointer,VPtr)。

虚函数表是一个存储着虚函数地址的表格,每个类都有一个唯一的虚函数表,其中包含该类的虚函数地址以及一些其他信息。每个对象都有一个指向其所属类的虚函数表的指针,这个指针称为虚函数表指针。当一个虚函数被调用时,程序会使用对象的虚函数表指针来查找该函数的地址,然后调用该函数。

在编译时,编译器会在每个类中添加一个虚函数表指针,用来指向类的虚函数表。当类被实例化时,对象会自动包含一个指向该类的虚函数表指针。当子类继承或覆盖了父类的虚函数时,子类会重新生成自己的虚函数表,并将其虚函数表指针指向新的虚函数表。

简单来说,虚函数表和虚函数表指针是C++实现虚函数动态绑定的重要机制。虚函数表保存了虚函数的地址,而虚函数表指针则指向类的虚函数表。当调用虚函数时,程序会使用对象的虚函数表指针来查找该函数的地址,然后调用该函数。

C++为了解决动多态引入了虚表和虚表指针。

什么是虚表?

对于每一个有虚函数的类,编译的时候都会生成一个虚表。注意,这个虚表是在编译的时候都已经生成。虚表里面一般有这个类对应的虚函数的地址,typeinfo地址等信息。

什么是虚表指针?

每个有虚函数的类的实例里面都有虚表指针。一个有虚函数的类的实例里面有一个或者多个虚表指针,数量取决于有多少个基类是有虚表的。

555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555

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

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

相关文章

html渲染的文字样式大小不统一解决方案

React Hooks 封装可粘贴图片的输入框组件(wangeditor)_react 支持图片拖拽的输入框-CSDN博客 这篇文章中的wangediter可粘贴图片的输入框,输入的文字和粘贴的文字在dangerouslySetInnerHTML渲染后出现了字体不统一的情况 在html中右键检查可…

openppp2 控制台回显窗口输出内容详解

本文介绍 openppp2 的控制窗口回显内容,以LINUX平台为例子,其它平台大同小异,区别只是多了一些额外的输出选项内容,本文会在下面补充。 在本文开始之前请查阅关联内容:openppp2 命令行接口详解-CSDN博客 控制台客户端…

自学鸿蒙HarmonyOS的ArkTS语言<三>路由跳转及传参

【官方文档传送门】 一、导入模块 import router from ohos.router二、新增页面配置 三、常用api 1、跳转到应用内的指定页面 build() {Row() {Button(下一页).onClick(() > {router.pushUrl({url: pages/Index2,params: {name: test}})})}.height(100%)}2、用应用内的某…

大模型如何改变世界?李彦宏:未来至少一半人要学会“提问题“

2023年爆火的大模型,对我们来说意味着什么? 百度创始人、董事长兼CEO李彦宏认为,“大模型即将改变世界。” 5月26日,李彦宏参加了在北京举办的2023中关村论坛,发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

Transformer中的Self-Attention和Multi-Head Attention

2017 Google 在Computation and Language发表 当时主要针对于自然语言处理(之前的RNN模型记忆长度有限且无法并行化,只有计算完ti时刻后的数据才能计算ti1时刻的数据,但Transformer都可以做到) 文章提出Self-Attention概念&…

LeYOLO 用于目标检测的新型可扩展和高效CNN架构 | 最新轻量化SOTA! 5GFLOP下无对手!

本改进已集成到 YOLOv8-Magic 框架。 论文地址:https://arxiv.org/pdf/2406.14239 代码地址:https://github.com/LilianHollard/LeYOLO/tree/main 在深度神经网络中,计算效率对于目标检测至关重要,尤其是在新型模型更倾向于速度而非计算效率(浮点运算次数,FLOP)的情况下…

Transformer1--self attention

目录 一、 Vector set as 输入二、 模型输出(三种)1 **n-to-n**2 n-to-13 n-to-m 三、self-attention1、问题引入2、self-attention3 self-attention 原理介绍 一、 Vector set as 输入 一段声音讯号: 图结构(graph)…

店员顾客起纠纷?EasyCVR+AI视频监控管理平台,助力连锁门店安全运营

近日,某品牌咖啡店店员与顾客起冲突登上了新闻热搜,一时间引发大量关注。随着门店完整的监控视频录像公开,大家才了解事情的原委,而并非网传的那样。 随着社会的进步和科技的发展,视频监控已成为各行各业不可或缺的安全…

红军九大技战法

一、动态对抗,线上社工持续信息追踪 发起攻击前,发起攻击前,尽可能多的搜集攻击目标信息,做到知己知彼,直击目标最脆弱的地方。攻击者搜集关于目标组织的人员信息、组织架构、网络资产、技术框架及安全措施信息&#x…

一分钟了解中小企业数字化转型如何进行?「建议收藏」

关于“中小企业数字化转型方法论”,其实网上已经有不少文章给出了一些方式方法,那么这里我再系统性的讲解一下。 一、中小企业为什么要实现数字化转型 首先要知道,中小企业为什么要实现数字化转型?当前,世界经济数字化…

社区团购系统智慧门店物流配送系统开发,支持小程序公众号。

目录 前言: 一、为什么要做社区团购小程序? 二、怎么做一个社区团购小程序? 三、制作属于自己的社区团购小程序有什么好处? 总结: 前言: 社区团购是针对小区居民或群体开发的在线购物平台,…

深入解析 Python dataclass:类属性与类方法解释

文章目录 dataclass实例属性和类属性自动设置属性 实例方法静态方法(staticmethod)和 类方法(classmethod)静态方法类方法 dataclass dataclass 是 Python 3.7 引入的一个装饰器,用于简化类的定义。 使用 dataclass …

AcWing 1801:蹄子剪刀布 ← 模拟题

【题目来源】https://www.acwing.com/problem/content/1803/【题目描述】 你可能听说过“石头剪刀布”的游戏。 这个游戏在牛当中同样流行,它们称之为“蹄子剪刀布”。 游戏的规则非常简单,两头牛相互对抗,数到三之后各出一个表示蹄子&#x…

玩玩大模型:总结归纳可以,策划创新拉垮

最近身边的人都在研究大模型。太深入的理解不了,有一些人会讲讲promt提示,学了几招。 比如: #角色 你是一个美食博主 #条件 我只有xxx元,在xxx.... #任务 找一家好吃的当地特色餐馆... 多试几次,有些结果很有参考价值…

函数栈帧的创建和销毁,带动图详细解析,带你大致分析汇编代码

目录 1.什么是函数栈帧 2.理解函数栈帧有什么用? 3.函数栈帧的创建和销毁解析 3.1什么是栈? 3.2 认识相关寄存器和汇编指令 3.3函数栈帧的创建和销毁解析过程 3.4函数的调用 3.5汇编代码 3.5.1函数栈帧的创建 3.5.2main函数部分 3.5.3Add函数…

策略模式编程

接口定义&#xff1a; public interface ProcessParserStrategy { List<ProcessInfo> parser(String osType, String processInfo); String getApp(); } public interface ConfigParserStrategy { List<ConfigInfo> parser(String configInfo); String getConfigT…

谷歌Chrome浏览器排查js内存溢出

1. 打开谷歌浏览器检查台 2. 点击memory 3. 点击开始快照录制&#xff0c;时隔一会儿录一次&#xff0c;多录几次 4. 进行快照对比

vue+element-plus完美实现跨境电商商城网站

目录 一、项目介绍 二、项目截图 1.项目结构图 2.首页 3.中英文样式切换 4.金钱类型切换 5.商品详情 6.购物车 7.登录 ​编辑 8.注册 9.个人中心 三、源码实现 1.项目依赖package.json 2.项目启动 3.购物车页面 四、总结 一、项目介绍 本项目在线预览&am…

[网络安全产品]---EDR

写在前面 前端时间看抖音&#xff0c;刷到周鸿祎介绍360为什么这么厉害&#xff0c;他提到一点就是360是全球第一个提出云查杀概念的公司&#xff0c;相比较传统的基于病毒特征库终端杀毒&#xff0c;360依托积累的庞大的信息数据能有效应对APT攻击。 然后又特意找了一下云查…

世界是软件定义的 - 正如硬件公司所证明的那样

很难相信&#xff0c;马克安德森&#xff08;Marc Andressen&#xff09;在13年前写下了他著名的博客&#xff0c;题为“软件正在吞噬世界”。在这篇文章中&#xff0c;他谈到了现代软件组织对传统企业造成的破坏。 十三年后&#xff0c;即使面对英伟达的平流层估值&#xff0…