[c++]多态的原理

引言

OOP的核心思想是多态性。多态性这个词源自希腊语,其含义是“多种形式”。我们把具有继承关系的多个类型称为多态类型,因为我们能使用这些类型的“多种形式”而无须在意它们的差异。引用或指针的静态类型与动态类型不同这一事实正是C++语言支持多态性的根本所在。

​ ——《C++11 Primer》

在C++语言中,当我们使用基类的引用或指针调用一个虚成员函数时会执行动态绑定。

​ ——《C++11 Primer》

上述内容表明,C++中多态的原理与动态绑定联系十分密切


静态绑定&动态绑定

静态绑定: 编译时确定函数地址

class Derive
{
public:void func(){cout << "Derive::func()";}
};
int main()
{Derive d;d.func();return 0;
}		

上述代码产生的汇编代码如图所示:
在这里插入图片描述

因为其在编译过程中就确定好了func()的地址,所以在运行时直接采用call指令的方式调转到func()的地址,这就是常见的静态绑定。

动态绑定: 运行时确定函数地址

class Base
{
public:virtual void func(){cout << "Base::func()";}
};
class Derive : public Base
{
public:virtual void func(){cout << "Derive::func()";}
};
int main()
{Base* d=new Derive;d->func();return 0;
}

上述代码产生的汇编代码如图所示:
在这里插入图片描述

这里的call指令并没有直接给出要跳转的地址,因为他不知道是调用Derive,还是Base的,所以在运行时就要根据提供的指针(存放到eax中),来确定应该跳转的具体地址,这就是动态绑定。

而具体如何进行这一动态绑定(如何确定是谁提供的指针),其核心就是虚表(虚函数表)


虚表(虚函数表)

先通过一组对比图查看现象

class Base
{
public://virtual void func()//void func(){cout << "Base::func()" << endl;}int _a = 0;
};
int main()
{Base d;return 0;
}

上述代码中,分别采用void func()和virtual void func()查看现象,其存储模型如下:

在这里插入图片描述

其中发现:

对于有虚函数的类,该类的对象的存储内容只有其成员变量(int _a)

对于有虚函数的类,该类的对象存储时,会额外存储一个指针(虚表指针),而该指针指向的内容就是其对应的虚表,这个虚表中的每行都是一个对应函数地址。


多态原理

原理1:虚表

如前可知,如果一个类中有虚函数,则这个类在创建的时候就会初始化一个虚表,该虚表存放的内容就是该类中所有虚函数的地址

同样,如果该类是派生类,继承了基类的虚函数,那么这个派生类也会初始化一个自己的虚表

class Base
{public:virtual void func(){cout << "Base::func()" << endl;}int _a = 0;
};
class Derive : public Base
{public:int _b = 1;
};
int main()
{Base d;Derive b;return 0;
}

在这里插入图片描述

上图中:

派生类中没有重写基类的虚函数,所以他们各自的虚表中func()函数的地址是一样的,说明他们调用同一个func()函数。

如果派生类中重写基类的虚函数,则会出现以下状况

在这里插入图片描述

此时,他们虚表中的func()函数就不是同一个func()函数了,此时对于不同的对象,指针或引用调用时,可能就会调用到不同的func()函数

原理2:赋值兼容/切割/切片

有了如上的知识铺垫,那么剩下最后一步就可以实现多态

C++中,派生类对象赋值给基类对象时会发生赋值兼容/切割/切片,这就导致了派生类会将自己存储空间里面的基类的那一部分拿出来

在这里插入图片描述

被拿出来的这一部分,含有虚表指针基类的成员变量
如果派生类重写了基类的虚函数,所以这一部分的虚表中存放的就是重写后的函数的地址。如此就完成了多态。

注意: 如前所说,当我们使用基类的引用或指针指向一个派生类对象时,调用他的虚函数才会执行动态绑定。所以单独进行赋值操作时,不会实现动态绑定

Derive b;
Base d=b;//不会产生动态绑定
Base *d=&b;//会产生动态绑定
Base &d=b;//会产生动态绑定

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

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

相关文章

ios搭建OpenGL环境

前言 本篇文章介绍在ios搭建OpenGL开发环境 在app的启动文章中&#xff0c;讲述了一个ios应用是如何启动的以及在IOS 13之后苹果公司推出的多窗口功能&#xff0c;通过app的启动这篇文章&#xff0c;我们基本能随心所欲的搭建一个app应用环境&#xff0c;搭建完成后的基本文件…

基于Python的深度学习的身份证识别考勤系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Text Mesh Pro图文混排如何对任何图片都能实现

1&#xff09;Text Mesh Pro图文混排如何对任何图片都能实现 2&#xff09;Unity iOS平台的小图占用特别大的内存 3&#xff09;只在编辑器内&#xff0c;纹理不开启Read&Write情况下&#xff0c;如何获取纹理所有颜色值 4&#xff09;准备在海外发行游戏&#xff0c;有哪些…

【3DGS】从新视角合成到3D Gaussian Splatting

文章目录 引言&#xff1a;什么是新视角合成任务定义一般步骤NeRF的做法NeRF的三维重建NeRF的渲染 3DGS的三维重建从一组图片估计点云高斯点云模型球谐函数参数优化损失函数和协方差矩阵的优化高斯点的数量控制(Adaptive Density Control)新的问题 3DGS的渲染&#xff1a;快速可…

通过html2canvas和jsPDF将网页内容导出成pdf

jsPDF参考&#xff1a;https://github.com/parallax/jsPDF html2canvas参考&#xff1a;https://github.com/niklasvh/html2canvas 或者 https://html2canvas.hertzen.com 思路 使用html2canvas将选中DOM生成截图对象将截图对象借助jsPDF导出为PDF文件 代码 这是一个示例&a…

如何编写接口测试用例

作为测试人&#xff0c;我们经常要对项目中的接口进行接口测试&#xff0c;那么在做接口测试的时候&#xff0c;如何写接口测试用例呢&#xff1f; 什么是接口测试 首先我们要了解一下&#xff0c;什么是接口测试&#xff1f; 那么首先要搞清楚&#xff0c;我们一般说的接口…

uniapp开发一个交流社区小程序

uniapp开发一个交流社区小程序 假期的时候简单学了一下uniapp&#xff0c;想开发一款类似百度贴吧的交流社区来练练手。本篇文章主要记录开发过程&#xff0c;文末附上项目地址。 主要需要开发以下几个页面。 信息页面热榜页面用户主页用户信息页 信息页面 该页面的功能主要…

【Android】RxJava系列01-基本概述和基本用法

少年啊&#xff0c;要永远相信美好的事情即将发生 【Android】RxJava系列01-基本概述和基本用法 1.RxJava的概述2.RxJava的作用3.观察者和被观察者4.背压5.RxJava的基本用法步骤一&#xff0c;创建Observer&#xff08;观察者&#xff09;步骤二&#xff0c;创建Observable&…

华为nova12系列:图片HDR显示,让你的照片全面升级!

你是不是也想给自己的照片加点料&#xff0c;让它们看起来更真实、捕捉到更多的细节和光影&#xff1f;不用愁&#xff0c;华为nova12系列就为你量身打造了图片HDR显示技术&#xff0c;让你的照片从此焕发绚丽光芒&#xff01; 回忆一下&#xff0c;在节日的夜晚想拍下绚丽的灯…

免费ai绘画软件选择哪个?

对于免费AI绘画软件的选择&#xff0c;因为每个软件都有其独特的优点和适用场景&#xff0c;可以根据个人的需求和技能水平来决定。以下是被广泛认可的AI绘画软件&#xff1a; 1、建e网AI-一款为建筑室内设计师提供AI绘图的智能工具&#xff0c;具有文字生图&#xff0c;方案优…

值得收藏的上千个涉及各个领域各个方面的免费的API接口服务,全网盘点并统计了网上诸多的免费API

值得收藏的上千个涉及各个领域各个方面的免费的API接口服务&#xff0c;全网盘点并统计了网上诸多的免费API。 一位开发者在GitHub上维护的免费API文档&#xff0c;不定期收录了互联网上开放的各种API接口。这些接口有些是来自第三方服务&#xff0c;你只需要在第三方注册成为会…

如何使用 FOFA 搜索引擎保姆级教程(附链接)

一、介绍 FOFA&#xff08;Fingerprinting Organizations with Advanced Tools&#xff09;是一家总部位于中国的网络安全公司提供的一款网络搜索引擎&#xff0c;专注于帮助用户收集和分析互联网上的设备和服务信息。FOFA 的主要特点包括&#xff1a; 设备指纹识别&#xff1…

面试150 颠倒二进制位 位运算分治 逻辑右移

Problem: 190. 颠倒二进制位 文章目录 思路复杂度位运算分治法 思路 &#x1f468;‍&#x1f3eb; 参考题解 >>>&#xff1a;逻辑右移&#xff08;符号位一起移动&#xff0c;高位补零&#xff09; 复杂度 时间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn) 空间…

Win10系统搭建个人hMailServer邮件服务结合内网穿透远程发邮件

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

计算机网络_1.6.1 常见的三种计算机网络体系结构

1.6.1 常见的三种计算机网络体系结构 1、OSI&#xff08;七层协议&#xff09;标准失败的原因2、TCP/IP参考模型3、三种网络体系结构对比 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 1、OSI&#xff08;七层协议&#xff09;标准失败的原因 &#xff08;1&#xf…

Django的web框架Django Rest_Framework精讲(四)

文章目录 1.DRF认证组件Authentication2.权限Permissions3.限流Throttling4.过滤Filtering5.排序6.分页Pagination7.异常处理 Exceptions8.自动生成接口文档 大家好&#xff0c;我是景天&#xff0c;今天我们继续DRF的最后一讲&#xff0c;Django的web框架Django Rest_Framewor…

STM32--揭秘中断(简易土货版)

抢占优先级响应优先级 视频学习--中断​​​​​​​

正则表达式可视化工具regex-vis

什么是正则表达式 &#xff1f; 正则表达式是对字符串操作的一种逻辑公式&#xff0c;就是用事先定义好的一些特定字符、及这些特定字符的组合&#xff0c;组成一个“规则字符串”&#xff0c;这个“规则字符串”用来表达对字符串的一种过滤逻辑。【百度百科】 正则表达式用简短…

【图论】基环树

基环树其实并不是树&#xff0c;是指有n个点n条边的图&#xff0c;我们知道n个点n-1条边的连通图是树&#xff0c;再加一条边就会形成一个环&#xff0c;所以基环树中一定有一个环&#xff0c;长下面这样&#xff1a; 由基环树可以引申出基环内向树和基环外向树 基环内向树如…

【新书推荐】5.2 位运算符

本节必须掌握的知识点&#xff1a; 位运算 示例十七 代码分析 汇编解析 5.2.1 位运算 位运算符如表5-2所示&#xff1a; 运算符 作用 示例 & 按位与 两个操作数同时为1&#xff0c;结果为1&#xff1b; | 按位或 两个操作数只要有一个为1&#xff0c;结果就为1&a…