虚函数 虚表指针

news2024/11/25 1:06:13

虚函数表和虚表指针


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

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

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

相关文章

工业无线网关在实际生产中的应用效果和价值-天拓四方

随着智能制造的快速发展,工业无线网关作为关键通信设备,在提升生产效率、优化生产流程、实现设备间的互联互通等方面发挥着越来越重要的作用。以下是一个关于工业无线网关在智能制造行业应用的具体案例,展示了其在实际生产中的应用效果和价值…

spring整合openAI大模型之Spring AI

文章目录 一、SpringAI简介1.什么是SpringAI2.SpringAI支持的大模型类型(1)聊天模型(2)文本到图像模型(3)转录(音频到文本)模型(4)嵌入模型(5&…

人工智能与大数据:新时代的技术融合与未来展望

引言 在信息化和数字化迅猛发展的今天,人工智能(AI)和大数据(Big Data)已成为推动社会变革和技术进步的两大支柱。随着互联网的普及、计算能力的提升以及数据获取手段的多样化,AI和大数据技术的应用愈发广泛…

使用GPG来解密和加密文件详解

文章目录 使用私钥解密文件示例步骤 注意事项加密文件前提条件导入公钥加密文件输出加密文件示例步骤注意事项邮箱不是必须的情况1:有多个公钥情况2:只有一个公钥示例步骤示例1:指定公钥ID或邮箱地址示例2:密钥环中只有一个相关的…

visual studio 创建c++项目

目录 环境准备:安装 visual studiovisual studio 创建c项目Tips:新建cpp文件注释与取消注释代码 其他 环境准备:安装 visual studio 官网:https://visualstudio.microsoft.com/zh-hans/ 以管理员身份运行VisualStudioSetup.exe …

超越AnimateAnyone, 华中科大中科大阿里提出Unimate,可以根据单张图片和姿势指导生成视频。

阿里新发布的UniAnimate,与 AnimateAnyone 非常相似,它可以根据单张图片和姿势指导生成视频。项目核心技术是统一视频扩散模型,通过将参考图像和估计视频内容嵌入到共享特征空间,实现外观和动作的同步。 相关链接 项目&#xff1…

leetcode 二分查找·系统掌握 寻找旋转排序数组中的最小值II

题目: 题解: 本题比普通的寻找旋转排序数组中的最小值多了一个数组中的元素可以重复这一点。 这会时原来的思路出现一个漏洞(大家感兴趣可以看看我做普通版寻找旋转排序数组最小值的思路),就是旋转后的数组中的第二个…

【AI】AI在创造还是毁掉音乐?

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

Vue3插件安装

一、volar插件安装 volar:Vue文件的语法提示和高亮提醒。volar已经更名为Vue - Official,其安装步骤如下。 (1)打开vscode,点击扩展面板,在搜索窗口中输入volar,选择Vue - Official进行安装。 (2&#xff0…

公网内网IP地址如何申请SSL证书实现HTTPS加密?

公网或者内网IP地址如果要实现HTTPS加密,必须申请特定的IP地址SSL证书。个人或者企业都可以申请。下面是IP地址SSL证书申请流程 IP SSL证书-JoySSLhttps://www.joyssl.com/certificate/select/ip_certificate.html?nid16 1 访问CA 登录提供IP地址证书的服务商—…

【MAUI】resource xml/file_paths (aka com.xxx.xxx:xml/ file _paths) not found.

APP2260:resource xml/file_paths (aka com.zettlercn.wms:xml/ file _paths) not found. This error is likely caused by an issue with the AndroidManifest.xml file or an Android manifest generation attribute in a source code file MAUI从6.0升级到8.0,调试发现资源…

程序猿大战Python——面向对象——面向对象的概念

两个重要概念 目标:了解什么是类,什么是对象? 要掌握Python面向对象的特性,首先需要了解两个重要概念:类、对象。 我们通过公司职员-张三为例子来解释说明。 类是抽象的概念,指的是:对某些事物…

学会python——获取文件信息(python实例八)

目录 1、认识Python 2、环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3、获取文件信息 3.1 代码构思 3.2 代码示例 3.3 运行结果 4、总结 1、认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的…

JavaWeb——Mysql的启动/登录/卸载

目录 1.Mysql服务器 2.Mysql的简单使用 2.1 启动Mysql: 2.2 登录Mysql 2.3 退出 3. 连接别人的数据库 4.卸载mqsql 1.Mysql服务器 安装了Mysql的计算机都成为Mysql服务器 2.Mysql的简单使用 2.1 启动Mysql: 第一种方法:搜索服务&am…

【QCustomPlot实战系列】QCPGraph堆叠面积图

在【QCustomPlot实战系列】QCPGraph堆叠图的基础上,使用setChannelFillGraph函数即可 static QCPScatterStyle GetScatterStyle(const QColor& color) {QPen pen(color, 2);return QCPScatterStyle(QCPScatterStyle::ssCircle,pen,Qt::white, 5); }static QCP…

【无线感知】【P4】无线感知手势识别- WIFI 感知边界

前言: 这篇是北大2022 在Ubicomp 上面的论文 《placement Matters: understanding the Effects of Device placements for WiFi Sensing》 放置很重要:了解设备放置对WiFi传感的影响 目录: 简介 感知质量定义(SSNR…

uniapp小程序button按钮去掉黑色线条

文章目录 导文去除方法 导文 在uniapp的button按钮中有一个莫名其妙的黑色线条 去除方法 button::after{border: none; }该问题并不是所有的手机机型都有,最好添加一下,以防用户手机端样式有问题。 您好,我是肥晨。 欢迎关注我获取前端学习…

LPD6803是专为LED(LED)灯光系统设计的驱动芯片

一般简介: LPD6803是专为LED(LED)灯光系统设计的驱动芯片,它采用先进的高压CMOS芯片工艺,提供三路恒流驱动和灰度调制输出,特别适合离散的多灰度全彩色灯光系统。 LPD6803芯片包括串行移位寄存器和级联驱动电路,灰度数据在时钟…

9.0分下跌至2.5分!110本SSCI影响因子下降!经济学领域SSCI最新IF汇总!

【欧亚科睿学术】 2023影响因子:经济学 1 影响因子概况 在170本经济学领域SSCI期刊中,有60本SSCI期刊2023年影响因子上涨。其中,期刊ECONOMIC POLICY由原来的2.5增长到了4.5,涨幅为2.0,也是经济学领域涨幅最大的SSCI…

【日记】梦到兄长要给鳄鱼换牙齿……(421 字)

正文 今天中午睡了一个小时多一点,做了一个很奇怪的梦。梦见兄长要给一条鳄鱼换牙齿,还说早上不好操作,要三天之后的中午或晚上,颇有一种翻黄历寻个良辰吉日之感。但我没那样大的耐性,便捏住鳄鱼的嘴,左摔右…