C++多态原理

news2025/1/15 6:46:06

请看下面的程序,该程序演示了多态类对象存储空间的大小。

#include <iostream>
using namespace std;
class A
{
	public:
	int i;
	virtual void func() {}
	virtual void func2() {}
};
class B : public A
{
	int j;
	void func() {}
};
int main()
{
	cout << sizeof(A) << ", " << sizeof(B); //输出 8,12
	return 0;
}

在 32 位编译模式下,程序的运行结果是:
8, 12
如果将程序中的 virtual 关键字去掉,输出结果变为:
4, 8
  对比发现,有了虚函数以后,对象所占用的存储空间比没有虚函数时多了 4 个字节。实际上,任何有虚函数的类及其派生类的对象都包含这多出来的 4 个字节,这 4 个字节就是实现多态的关键——它位于对象存储空间的最前端,其中存放的是虚函数表的地址。
  每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着该虚函数表的指针(可以认为这是由编译器自动添加到构造函数中的指令完成的)。
  虚函数表是编译器生成的,程序运行时被载入内存。一个类的虚函数表中列出了该类的全部虚函数地址。例如,在上面的程序中。
类 A 对象的存储空间以及虚函数表(假定类 A 还有其他虚函数)如下图所示。
在这里插入图片描述
类 B 对象的存储空间以及虚函数表(假定类 B 还有其他虚函数)如下图所示。
在这里插入图片描述
  多态的函数调用语句被编译成根据基类指针所指向的(或基类引用所引用的)对象中存放的虚函数表的地址,在虚函数表中查找虚函数地址,并调用虚函数的一系列指令。

假设 pa 的类型是 A*,则 pa->func() 这条语句的执行过程如下:

  1. 取出 pa 指针所指位置的前 4 个字节,即对象所属的类的虚函数表的地址(在 64 位编译模式下,由于指针占 8 个字节,所以要取出 8 个字节)。如果 pa 指向的是类 A 的对象,则这个地址就是类 A 的虚函数表的地址;如果 pa 指向的是类 B 的对象,则这个地址就是类 B 的虚函数表的地址。

  2. 根据虚函数表的地址找到虚函数表,在其中查找要调用的虚函数的地址。不妨认为虚函数表是以函数名作为索引来查找的,虽然还有更高效的查找方法。如果 pa 指向的是类 A 的对象,自然就会在类 A 的虚函数表中查出 A::func 的地址;如果 pa 指向的是类 B的对象,就会在类 B 的虚函数表中查出 B::func 的地址。类 B 没有自己的 func2 函数,因此在类 B 的虚函数表中保存的是 A::func2 的地址,这样,即便 pa 指向类B 的对象,pa->func2();这条语句在执行过程中也能在类 B 的虚函数表中找到 A::func2 的地址。

  3. 根据找到的虚函数的地址调用虚函数。

  由以上过程可以看出,只要是通过基类指针或基类引用调用虚函数的语句,就一定是多态的,也一定会执行上面的查表过程,哪怕这个虚函数仅在基类中有,在派生类中没有。
  多态机制能够提高程序的开发效率,但是也增加了程序运行时的开销。虚函数表、各个对象中包含的 4 个字节的虚函数表的地址都是空间上的额外开销;而查虚函数表的过程则是时间上的额外开销。
  在计算机发展的早期,计算机非常昂贵稀有,运行速度慢,计算机的运算时间和内存是宝贵的,因此人们不惜多花人力编写运行速度更快、更节省内存的程序;如今,计算机的运算时间和内存往往没有人的时间宝贵,运算速度也很快,因此,在用户可以接受的前提下,降低程序运行的效率以提升人员的开发效率就是值得的了。“多态”的应用就是典型例子。

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

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

相关文章

VBA之正则表达式(41)-- 快速标记两个星号之后的字符

实例需求&#xff1a;工作表中的数据保存在A列~G列&#xff0c;现需要识别D列中包含超过两个星号的内容&#xff0c;并将第3个星号及其之后的字符设置为红色字体&#xff0c;如图所示。 示例代码如下。 Sub Demo1()Dim objRegExp As ObjectDim objMatch As ObjectDim strMatch…

【10】linux命令每日分享——cp复制文件和目录

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

Altium Designer v23.2.1.34 PCB板设计软件中文特别版

Altium Designer 中文特别版是一款功能强大的电子设计自动化(EDA)软件,它提供了一个完整的设计环境,可以帮助电子工程师快速设计、模拟、仿真和制造电子产品。Altium Designer 中文特别版拥有丰富的功能,包括电路设计、PCB设计、回流焊接、3D设计、仿真等,可以帮助用户快…

【深度学习 01】安装环境详解之 miniconda

欢迎关注『youcans的深度学习课』系列&#xff0c;持续更新中… 【深度学习 01】安装环境之 miniconda 【深度学习 02】PyTorch CPU版本安装与环境配置 【深度学习 01】 安装环境详解之 miniconda 1. conda/Anaconda/miniconda conda可以理解为一个工具&#xff0c;也是一个可…

TensorFlow-Keras - 一文搞懂 TF 常用矩阵计算方法

目录 一.引言 二.tf.multiply 1.常规乘法 2.乘以标量 3.不规则乘法 三.tf.matmul 1.常规矩阵相乘 2.多维矩阵相乘 四.tf.tensordot 1.axes1 2.axesN 3.axesTuple 4.axesArray(Tuple()) 五.K.dot 六.K.batch_dot 1.不指定 axes 2.指定 axes 为数字 3.指定 axe…

【观察】连续八年霸榜云数据库“领导者”,揭秘亚马逊云科技背后的“统治力”...

日前&#xff0c;全球市场分析机构 Gartner发布《2022 云数据库管理系统魔力象限》报告。其中&#xff0c;在Gartner本次魔力象限报告评估的20家供应商中&#xff0c;亚马逊云科技在纵轴“执行能力”和横轴“愿景完整性”两个维度分别处于最高、最右位置&#xff0c;这也是亚马…

Zigbee物联网组网

物联网的核心和基础是互联网&#xff0c;物联网是在互联网基础上的延伸和扩展的网络&#xff0c;然而在物联网当中基于海量数据的无线传感网是物联网极具代表的网络之一&#xff0c;其用户端延伸和扩展到了任何物品与物品之间&#xff0c;进行信息交换和通信。 硬件设备及连接&…

PPC Insights系列:洞见安全多方图联邦

开放隐私计算开放隐私计算开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服务区”。183篇原创内容公众号知…

NetCore使用SkyWalking

官网中文文档&#xff1a;SkyWalking 极简入门 | Apache SkyWalking一、引用依赖新建一个项目&#xff1a;Cbf.SkyWalking.ServiceInstancenuget安装&#xff1a;SkyAPM.Agent.AspNetCore二、launchSettings.json添加这两行配置或者在这里添加这两行也行&#xff1a;三、需要添…

界面组件DevExpress WinForms v22.2 - 全面升级数据展示功能

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

某马程序员NodeJS速学笔记

文章目录前言一、什么是Node.js?二、fs文件系统模块三、Http模块四、模块化五、开发属于自己的包模块加载机制六、Express1.初识ExpressGET/POSTnodemon2.路由模块化3.中间件中间件分类自定义中间件4. 跨域问题七、Mysql模块安装与配置基本使用Web开发模式Session认证JWT八、大…

MySQL查询操作

系列文章目录前言一、简单查询SELECT子句SELECT后面之间跟列名DISTINCT,ALL列表达式列更名WHERE子句WHERE子句中可以使用的查询条件比较运算BETWEEN...AND...集合查询&#xff1a;IN模糊查询LIKE空值比较&#xff1a;IS NULL多重条件查询SELECT 的基本结构ORDER BY子句排序聚集…

vue导出excel

1、下载依赖 npm install --save xlsx file-saverps&#xff1a;我下载完依赖后再运行会报错&#xff0c;偶尔情况&#xff0c;没找到原因&#xff0c;只需要卸载重新npm install就好 2、新建一个写公共js方法的文件**&#xff0c;如果你有的话 &#xff0c;写在里面就好 然…

Mysql 用户管理、权限管理(含用户密码修改)

和Linux 系统一样&#xff0c;也有着自己独有的用户管理系统&#xff0c;MySQL所有的用户信息都被保存在mysql数据库中的user表中。 目录 1、用户信息 2、用户管理 (1) 创建用户 (2) 删除用户 (3) 修改用户密码 3、用户权限管理 (1) 赋予权限&#xff08;grant&#xff…

Mysql5.7+Orch+proxysql+keepalive

架构设计 通过gtid配置MySQL主从&#xff0c;通过orch实现高可用&#xff0c;orch通过raft实现自身的高可用&#xff0c;通过proxysql实现读写分离&#xff0c;proxysql可自身可以配置集群&#xff0c;通过keepalive实现虚拟IP漂移&#xff0c;keepalive可以自身配置集群 配…

蓝桥杯嵌入式LED流马灯(使用HAL_Delay、操作寄存器、使用定时器)

1.STM32CubeMX的配置 将PC8-PC15设置为GPIO_Output模式&#xff0c;将PD2也设置为GPIO_Output模式。 通过原理图知&#xff0c;LED&#xff08;PC8-PC15&#xff09;低电平有效&#xff0c;锁存器(PD2)高电平有效。 初始化时我将LED设置为高电平&#xff0c;熄灭状态&#xff0…

MyBatis - 09 - 自定义映射resultMap

文章目录1 准备工作1.1 建表1.2 创建实体类1.3 引出一个问题方案1方案2方案32.完整代码项目结构EmpMapper接口Emp类SqlSessionUtils工具类EmpMapper.xmljdbc.propertieslog4j.xmlmybatis-config.xmlResultMapTest完整代码在后面 1 准备工作 1.1 建表 t_emp 添加测试数据&…

AOP在PowerJob中的使用,缓存锁保证并发安全,知识细节全总结

这是一篇简简单单的文章&#xff0c;需要你简简单单看一眼就好&#xff0c;如果有不明白的地方&#xff0c;欢迎留言讨论。 在之前的文章中出现过一次AOP的使用&#xff0c;就是在运行任务之前&#xff0c;需要判断一下&#xff0c;触发该任务执行的server&#xff0c;是不是数…

[神经网络]图神经网络(GNN)

一、概述 1.图 图用来表示一些实体(entities)之间的关系(实体表示为点(node)&#xff0c;关系表示为边(edge))。 关系分为有方向和无方向 2.数据的图表示 以图像文件为例&#xff0c;我们可以用邻接矩阵来表示一张图像。每个点表示一个像素点&#xff0c;若一个像素点有x个相邻…

重生之我是SVG(1)-入门

概述 引用一句来自MDN的一句话&#xff1a; SVG 图像是使用各种元素创建的&#xff0c;这些元素分别应用于矢量图像的结构、绘制与布局。在这里&#xff0c;您可以找到每个 SVG 元素的参考文档。 SVG 文件可以直接插入网页&#xff0c;成为 DOM 的一部分&#xff0c;然后用 Ja…