[C++]多态是如何调用不同的函数对象的?

        多态调用不同的函数对象涉及C++中的虚函数表(VTable)、虚函数指针(VPtr)以及动态绑定机制。下面详细解析这一底层逻辑:

1. 虚函数表(VTable)与虚函数指针(VPtr)

        在C++中,当一个类包含至少一个虚函数时,编译器会为该类创建一个**虚函数表**(Virtual Function Table, VTable)。VTable是一个数据结构,通常是一个数组,其元素是对应虚函数的地址。每个类都有自己的VTable,且派生类会继承并可能扩展基类的VTable。

        同时,编译器会在每个含有虚函数的类的实例中插入一个隐藏的指针,称为**虚函数指针**(Virtual Function Pointer, VPtr)。VPtr指向该实例所属类的VTable。这样,每个类实例都可以通过其VPtr访问到其类的VTable,进而调用相应的虚函数。

2. 对象内存布局与VPtr位置

        一个包含虚函数的类实例在内存中的布局大致如下:

- VPtr:位于对象内存的起始位置(通常情况,具体取决于编译器实现)。
- 成员变量:紧跟在VPtr之后,按照声明顺序排列。
- 派生类独有的成员(如果有):如果该类是派生类,那么基类部分之后是派生类独有的成员变量和函数。

3. 多态调用过程

现在我们通过一个具体的例子来说明多态调用的底层逻辑:

class Base {
public:virtual void funcA() { std::cout << "Base::funcA()" << std::endl; }virtual void funcB() { std::cout << "Base::funcB()" << std::endl; }
};class Derived : public Base {
public:void funcA() override { std::cout << "Derived::funcA()" << std::endl; }
};int main() {Base* basePtr = new Derived();basePtr->funcA();delete basePtr;return 0;
}

在上述代码中,当执行`basePtr->funcA()`时,发生了多态调用:

1. 查找VPtr:

首先,CPU通过`basePtr`找到对象的起始地址,即VPtr所在位置

2. 获取VTable:

然后,CPU从VPtr处加载出指向VTable的地址。

3. 定位虚函数地址:

接着,CPU根据VTable的布局,索引到`funcA`在VTable中的位置,取出对应虚函数的地址。在本例中,basePtr实际指向的是Derived对象,因此VTable对应Derived类,其中的funcA条目指向Derived::funcA()

4. 执行函数:

最后,CPU跳转到刚刚获取的函数地址执行代码,即Derived::funcA()

4. 动态绑定与静态绑定对比

        相比之下,非虚函数或非通过基类指针/引用调用的虚函数调用是静态绑定的。在编译期间,函数调用的目标地址就已经确定。而多态调用是**动态绑定**(Runtime Binding),即函数调用目标在运行时根据对象的实际类型确定,这就是多态性得以实现的关键机制。

总结

        C++中的多态调用通过虚函数表(VTable)、虚函数指针(VPtr)以及动态绑定机制实现。当通过基类指针或引用调用虚函数时,编译器和运行时环境会依据对象的实际类型,通过其VPtr找到正确的VTable,再从VTable中查找出对应虚函数的地址并执行。这种机制确保了同一消息(函数调用)在不同对象(基类与派生类)上表现出不同的行为,实现了多态性。

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

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

相关文章

【每日刷题】Day22

【每日刷题】Day22 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1669. 合并两个链表 - 力扣&#xff08;LeetCode&#xff09; 2. 11. 盛最多水的容器 - 力扣&#…

回归用户本真的业务价值需求,聚焦成本优化与内核能力提升——专访云和恩墨张程伟、金毅...

数据库作为企业核心业务系统的重要基座&#xff0c;其技术架构和性能都将直接影响企业的运营效率与成本。在2024“数据技术嘉年华”大会现场&#xff0c;笔者采访到了云和恩墨本原数据的两位技术合伙人——MogDB数据库研发负责人张程伟、下一代原生HTAP企业级数据库研发负责人金…

Process in Semiconductor(半导体工艺)

Front-End Process in Semiconductor 引言正文Front-endBack-endFront-end of lineProcess flowBack-end of lineSiN seal layerCVDLPCVDPECVDSOI PSVSOI ACTSOI PSV+引言

语音生成表情SlefTalk

目录 SlefTalk官网 依赖项安装 windows安装psbody templates.pkl 下载地址&#xff1a; 推理代码&#xff1a; diffspeaker SlefTalk官网 GitHub - psyai-net/SelfTalk_release: This is the official source for our ACM MM 2023 paper "SelfTalk: A Self-Supervi…

NSQ消息队列---总结篇

架构 概念 nsqlookup&#xff1a;存储了nsqd的元数据和服务信息(endpoind),向消费者提供服务发现功能, 向nsqadmin提供数据查询功能。 nsqd: 是接收、队列和传送消息到客户端的守护进程。 nsqadmin&#xff1a;简单的管理界面,展示了topic, channel以及channel上的消费者,也…

【漏洞复现】号卡极团管理系统 index.php SQL注入漏洞

0x01 产品简介 号卡极团管理系统是一款专为号卡行业打造的管理系统&#xff0c;它具备一系列强大的功能&#xff0c;能够满足号卡行业推广人员在业务运营中的各类需求。 0x02 漏洞概述 号卡极团管理系统存在SQL注入漏洞&#xff0c;未授权的攻击者可以通过该漏洞获取数据库敏…

Playwright

一&#xff1a;选择器 个人理解&#xff0c;其实跟css选择器一样 1、某个类的第一个 .your-class-name:first-of-type2、某个类的第一个子元素 :first-child

数据库关系模式分解 - 无损连接和保持函数依赖性

文章目录 1 概述1.1 关系模式分解的好坏标准 2 无损连接验证算法 1 概述 1.1 关系模式分解的好坏标准 书上的算法太抽象了&#xff0c;咱不好理解&#xff0c;以下举例说明。一个关系可以有很多种分解方法&#xff0c;如何判断分解的好与坏呢&#xff1f; ① 查询时的连接操作…

类的六个构造函数相关干货

构造函数 特点 1.名字与类名相同 2.无返回值 3.对象实例化的时候编译器自动调用这个函数 4.构造函数可以重载&#xff08;无参构造函数&#xff0c;拷贝构造等&#xff09; 5.如果类中没有显式定义构造函数&#xff08;深拷贝&#xff09;&#xff0c;则编译器会自动生成一个…

CSS基础——2.CSS选择器

1. 通用选择器 通用选择器用星号*表示,它不匹配某个特定的 HTML 元素,而是匹配 HTML 文档中的每个元素,开发中通常使用通用选择器来清除 HTML元素中默认的内外边距 通用选择器格式:*{} * { margin: 0 auto; padding: 0; } 2. 标签选择器 根据标签的名字 进行选择匹…

抖音阳哥:选品师项目究竟能不能算蓝海项目?

在当今这个信息爆炸的时代&#xff0c;短视频平台如抖音已经成为了人们获取信息、娱乐休闲的重要渠道。抖音上涌现出许多具有影响力的网红&#xff0c;他们不仅分享自己的生活点滴&#xff0c;还常常推荐一些创业项目或商业模式。其中&#xff0c;阳哥分享的选品师项目引起了广…

STM32H750片外QSPI下载算法文件(stldr)生成

STM32H750片外QSPI下载算法文件&#xff08;stldr&#xff09;生成 &#x1f33f;相关篇《STM32H750片外QSPI启动配置简要》&#x1f4cc;参考实现资料&#xff1a; https://github.com/lchnu/STM32H750XBH_ARTPIQSPI_W25Q64JV https://gitee.com/wangchief/H750_W25QXX ✨利…

WPF之Label

Label在wpf中表示控件的文本标签&#xff0c;并提供访问密钥支持。 常用属性: 属性 HorizontalContentAlignment文本水平内容排列VerticalContentAlignment垂直内容排列width宽height高fontsize字体大小fontfamily字体样式fontwidth字体粗细 具体写法 <Label Width"20…

JavaScript常用的Hook脚本

页面最早加载代码Hook时机 在source里 用dom事件断点的script断点然后刷新网页&#xff0c;就会断在第一个js标签&#xff0c;这时候就可以注入代码进行hook 监听 键盘 与 鼠标 事件 // 判断是否按下F12 onkeydown事件 /* 提示&#xff1a; 与 onkeydown 事件相关联的事件触…

风格迁移adaIN 和iT的adaLN

文章目录 BN、LN、IN、GN的区别![](https://img-blog.csdnimg.cn/direct/d38c005616f145cba2aa1c4c2e046be0.png)图像风格迁移adaINDiT adaLN BN、LN、IN、GN的区别 BatchNorm&#xff1a;batch方向做归一化&#xff0c;算NxHxW的均值&#xff0c;对小batchsize效果不好&#x…

「Kafka」Kafka基础知识入门介绍(三)

「Kafka」Kafka基础知识入门介绍&#xff08;三&#xff09; 一、消息主题1. 创建主题 二、生产数据1. 命令行模式2. Java代码模式 三、消费数据1. 命令行模式2. Java代码模式 「Kafka」Kafka理论知识解读&#xff08;一&#xff09; 「Kafka」Kafka安装和启动&#xff08;二&a…

【kotlin】利用by关键字更加方便地实现装饰器模式

关于kotlin中的by关键字的用法&#xff0c;kotlin官方文档属性委托这一节讲得很清楚。 简单来说就是这样的&#xff0c;假设存在一个接口Component如下&#xff1a; interface Component {fun method1(): IntArrayfun method2(a: Int)fun method3(a: Int, str: String) }那么对…

React-性能优化的手段

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:React-性能优化的手段 目录 React 性能优化的手段有哪些&#xff1f; 一、是什么 二、如何做…

【无标题】cocos与外部laya或者web交互

一.电脑&#xff1a; 电脑网页&#xff1a;cocos --->laya this.webview._impl._iframe.contentWindow.postMessage("cocosToLaya", "*");//laya //这里是浏览器环境下&#xff0c; 接收web传过来的消息//cocos window.addEventListener(&q…

【汇编语言】流程转移和子程序

【汇编语言】流程转移和子程序 文章目录 【汇编语言】流程转移和子程序前言一、“转移”综述二、操作符offset三、jmp指令jmp指令——无条件转移jmp指令&#xff1a;依据位移进行转移两种段内转移远转移&#xff1a;jmp far ptr 标号转移地址在寄存器中的jmp指令转移地址在内存…