C++从入门到入土(七)——多态
目录
前言
多态的概念
多态的定义
虚函数的介绍
虚函数的重写/覆盖
析构函数的重写
override和final关键字
纯虚函数和抽象类
重写/重载/隐藏总结
多态的原理
小结
前言
C++一共有三个特性,封装、继承和多态,在前面的文章中,我们分别介绍了封装和继承的概念,现在本篇文章将完成C++特性的最后一块拼图——多态。在实际生活中我们会看到这种情况,一个人有不同的身份,比如在学校的时候是老师,在家是孩子,工作了是老师;我们在买票时,成人全票,儿童半价;动物的叫声,狗是“汪汪”,猫是“喵喵”等这些都是多态的实例,多态通俗将就是一个事物的多种状态,那么有了这个认识,我们将开启多态的世界。
多态的概念
多态通俗讲就是多种状态,分为两种:编译时多态和运行时多态。我们在前面介绍的函数重载、类模板就是编译时多态,我们在这里不做过多介绍,我们今天主要介绍运行时的多态。
那么多态有什么作用呢?我们在编写代码时可能会出现下面的情况:基类当中有一个函数实现了一种功能,派生类在继承了基类后针对这个函数的功能要做出相应的调整,但函数结构大体不变,还是实现了这个功能,只不过实现方式不同,那么我们此时就可以使用多态定义这个新的函数,这样就可以保证基类代码不变的情况下,通过在派生类中的改变达到某种需求。这就是多态的核心作用
多态的定义
多态的实现需要两个条件:
1.必须是基类的指针或引用调用虚函数
2.被调用的必须是虚函数,并且完成了重写/覆盖
接下来我们将介绍虚函数和重写的概念。
虚函数的介绍
类成员函数名称前加上virtual就构成了虚函数,但是非成员函数不能用virtual修饰。
虚函数的重写/覆盖
既然要保证基类代码不变的情况下,通过在派生类中添加相关功能达到某种需求,那么C++为我们提供的解决方案就是虚函数的重写/覆盖。
概念:派生类中有一个与基类完全相同的虚函数,称派生类重写了基类的虚函数
值得注意的是:派生类的虚函数如果不在前面加virtual也构成重写(但是在实际操作过程中建议在派生类中加上virtual)。重写是一种特殊的隐藏,即:不构成重写就是隐藏。
那么有了虚函数和重写后,我们可以参考下面代码,更加深入的理解多态的概念:
class Animal
{
public:virtual void sound(){cout << "啊啊" << endl;}
protected:string _name;int _weight;string _type;
};
class Dog :public Animal
{
public:virtual void sound(){cout << "汪汪" << endl;}
};void func(Animal&a)
{a.sound();
}
上述代码运行结果如下所示:

我们可以看到,通过传不同的类就调到了不同的函数,这就是多态要完成的任务。
那么虚函数的重写可以实现不同函数的调用,这是为什么呢?实际上重写就是组合,编译器将派生类重写的函数内容与基类虚函数的声明相互组合,从而实现函数的拼接调用。
析构函数的重写
C++从入门到入土(六)——继承的介绍
我们在前面继承章节中介绍默认成员函数时,对析构函数是这么说的:派生类的析构函数会在对象生命周期结束后自动调用基类的析构函数清理基类成员,因为这样才能保证先清理基类再清理派生类的顺序。(析构先子后父)这是因为析构函数在编译时统一将名称改为destructor(),与多态有关这是为什么呢?
实际上基类的析构函数是虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类析构函数构成重写,虽然它们的名称看起来不符合重写规则,但实际上编译器做了特殊处理,将他们的名称统一处理成destructor(),这样就支持了函数重写,所以析构函数在定义时建议加上virtual。
override和final关键字
C++标准对于重写的定义是比较严格的,有时候我们会因为疏忽大意导致函数无法完成重写,因此C++为我们提供了override关键字,用来检测函数是否发生重写,其定义方式是:在派生类重写的虚函数后面加上override。
如果我们不想让这个函数发生重写,那么C++标准为我们提供了final关键字,其定义方式是:在基类不想发生重写的函数后面加上final。
override和final使用如下所示:

纯虚函数和抽象类
纯虚函数:在虚函数后面加上=0,则这个函数就是纯虚函数,纯虚函数不需要定义实现,因为不需要重写,只要声明即可。
抽象类:包含纯虚函数的类叫做抽象类,如果派生类继承之后不重写纯虚函数,那么派生类也是抽象类,纯虚函数在某种程度上强制派生类重写虚函数,因为不重写实例化不出对象。
重写/重载/隐藏总结
重载:两个函数在同一作用域,函数名相同,参数不同,参数的类型或个数不同,返回值可以相同,可以不同
重写:两个函数分别在基类和派生类不同的两个作用域中,函数名,参数,返回值必须相同(协变除外),两个函数必须是虚函数
隐藏:两个函数或变量分别在基类和派生类两个不同的作用域,函数名相同,两个函数只要不是重写就是隐藏
多态的原理
在讲解多态之前,我们先来看一个问题:
class A
{
public:virtual void func(){cout << "func()" << endl;}
private:int _a;char _b;
};
int main()
{A a;int size = sizeof(a);cout << size << endl;return 0;
}
你们觉得上面代码的运行结果是什么(32位)?如果根据结构体对齐的概念,我们可以知道,这个结果应该是8,但事实真是如此吗?我们运行代码:

结果与我们推测的有所差异,这是因为什么呢?我们进行调试:

我们可以看到a当中保存了三个变量,那么应该是这个_vfptr导致大小的改变,根据后面的ptr我们可以推测这个应该是指针,那么在32位机器下,指针大小应该是四字节所以其大小变为了12字节,那么这个_vfptr是什么东西呢?实际上这个_vfptr是一个虚函数指针数组,又叫虚函数表,所有的虚函数都是存储在这个虚表当中,我们在运行过程中就是通过虚表找到每个虚函数的地址,然后实现对应的函数调用。
小结
本篇文章我们完成了C++特性的最后一块拼图——多态,通过多态我们可以更加灵活的实现代码的编辑,为我们程序的书写提供了便利,受限于博主的知识水平,可能文章当中有所纰漏,欢迎大家指正,接下来我们继续更新C++从入门到入土系列,如果觉得我的文章对您有所帮助的话,希望您能够点赞、关注加收藏,您的支持是我创作的最大动力
相关文章:
C++从入门到入土(七)——多态
目录 前言 多态的概念 多态的定义 虚函数的介绍 虚函数的重写/覆盖 析构函数的重写 override和final关键字 纯虚函数和抽象类 重写/重载/隐藏总结 多态的原理 小结 前言 C一共有三个特性,封装、继承和多态,在前面的文章中,我们分别…...
新闻网页信息抽取
1. 网页信息抽取 问题定义:对新闻网页(输入为HTML)提取结构化信息,包括标题、发布时间、作者、正文、图片等。 动机:由于网页(大多数为HTML格式)通常带有很多标签、样式、脚本等信息࿰…...
MySQL中有哪些索引
1,B-Tree索引:常见的索引类型 2,哈希索引:基于哈希表实现,只支持等值查询 ,只有Memory存储引擎和NDB Cluster存储引擎显示支持哈希索引 3,全文索引:可在字符列上创建(T…...
Docker 部署Spring boot + Vue(若依为例)
首先我们要在docker中安装好环境镜像 jdk. mysql. redis. nginx 镜像安装我们在上一篇文章中已说明,请大家自行查看。 下面我介绍部署步骤 部署后台jar 在你的工作目录下新建application 用来存放后台jar包 1.将打好的jar包上传 2.编写Dockerfile文件&#…...
PDF文件里到底有什么?
PDF 文档结构由多个组件组成,这些组件决定了文本、图像和其他元素的存储和显示方式。PDF 是一种二进制文件格式,这意味着您无法在文本编辑器中直接编辑 PDF 文件。添加或删除一个字符都可能导致整个文件损坏! PDF 文件结构 理解 PDF 文档结…...
FANUC机器人几种常用的通讯网络及接口
FANUC机器人几种常用的通讯网络及接口 Devicenet 网络通讯接口,接口为5针线 (规定用的机架为 81-84) PROFIBUS 网络通讯接口,针脚为2针(规定用的机架为 67) Intemet 网络通讯接口(常用的网线接口…...
实用插件分享:@plugin-web-update-notification/vite 的使用指南
实用插件分享:plugin-web-update-notification/vite 的使用指南 在前端开发的过程中,及时告知用户网页有更新是提升用户体验的一个重要方面。plugin-web-update-notification/vite 就是一款能够轻松实现网页更新通知功能的插件,下面就来详细…...
k8s 修改节点驱逐阈值
编辑 /var/lib/kubelet/config.yaml 文件 kind: KubeletConfiguration evictionHard:nodefs.available: "5%" # 降低磁盘压力触发阈值imagefs.available: "10%" # 调整容器镜像存储触发阈值nodefs.inodesFree: "3%...
IEC61850标准下MMS 缓存报告控制块 ResvTms详细解析
IEC61850标准是电力系统自动化领域唯一的全球通用标准。IEC61850通过标准的实现,使得智能变电站的工程实施变得规范、统一和透明,这大大提高了变电站自动化系统的技术水平和安全稳定运行水平。 在 IEC61850 标准体系中,ResvTms(r…...
解数独 (leetcode 37
leetcode系列 文章目录 一、核心操作二、外层配合操作三、核心模式代码总结 使用二维递归,不管在哪一层都对矩阵进行全部遍历 一、核心操作 建立判断是否有效函数,对 i j 位置是否能放入k进行判断,由于此时还没有放置k,则可以直…...
人工智能与人的智能,思维模型分享【2】沉没成本
**沉没成本(Sunk Cost)** 是指已经发生且无法收回的成本(时间、金钱、精力等)。沉没成本思维模型的核心原则是:理性决策应基于未来可能的收益与成本,而非被已经无法改变的历史投入所影响。陷入沉没成本陷阱…...
Redis 部署方式有哪些
以下是 Redis 主从复制和分布式部署的详细方法和步骤: 1.Redis 主从复制部署 架构 主从复制是 Redis 最基本的分布式机制,通过将数据从主节点(Master)复制到多个从节点(Slave),实现读写分离和数…...
艾尔登复刻Ep1——客户端制作、场景切换、网络控制
需要添加的插件内容 Netcode for GameObjects:是一个为 Unity 游戏开发提供高级网络功能的 SDK。它的主要作用是允许开发者在其 GameObject 和 MonoBehaviour 工作流中集成网络功能,并且可以与多种底层传输层协议兼容。 具体内容请看:https:…...
【视频】ffmpeg、Nginx搭建RTMP、HLS服务器
1、源码安装Nginx 1)源码下载 因为要使用Nginx的模块nginx-rtmp-module,所以要下载 nginx 和 nginx-rtmp-module 的源码。 下载地址: http://nginx.org/en/download.html https://github.com/arut/nginx-rtmp-module/tags2)解压、配置 在同一个目录中解压 nginx 和 nginx…...
基于YOLO11深度学习的遥感视角地面房屋建筑检测分割与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
Java中常见的PO、VO、DAO、BO、DO、DTO、POJO、Query类解释(通俗易懂)
文章目录 先点击收藏和点赞,切勿白嫖,感谢一丶PO(persistant object)持久对象二丶VO(value object)值对象三丶DAO(Data Access Objects) 数据访问对象接口四丶BO/DO(Business Object) 业务对象层五丶DTO(Data Transfer Object) 数据传输对象六丶POJO(Plain Old Java Objects) 简…...
完美解决ElementUI中树形结构table勾选问题
完美解决ElementUI中树形结构table勾选问题 实现功能效果图全选取消全选取消父节点取消某个子节点 关键代码 实现功能 1. 全选/取消全选,更新所有节点勾选状态 2. 勾选父/子节点,子/父节点状态和全选框状态更新 效果图 全选 取消全选 取消父节点 取消某…...
laravel项目中使用FFMPeg 剪裁视频
# 运行环境需安装的软件 ffmpeg # 安装的扩展 pbmedia/laravel-ffmpeg: ^8.3 # 扩展文档 https://packagist.org/packages/pbmedia/laravel-ffmpeg # 引入的类 use FFMpeg\Coordinate\TimeCode; use FFMpeg\Format\Video\X264; use FFMpeg\Exception\RuntimeException; use …...
docker基本应用和相关指令
文章目录 概要镜像管理容器操作网络管理数据卷管理其他常用指令典型场景示例小结 概要 Docker的命令通常分为几个大类,比如镜像管理(images)、容器管理(containers)、网络(network)、数据卷&…...
文件解析漏洞靶场集锦详解
一、IIS解析漏洞 环境安装:windows2003iis6 1.目录解析 .asp文件夹中的任意文件都会被当做asp文件去执行 1.在iis6的网站根目录新建⼀个名为1.asp的文件 2. 在1.asp中新建⼀个jpg文件。内容为 <%now()%>asp代码 3.在外部浏览器中访问iis⽹站中的1.jpg 发现…...
基于Java + Redis + RocketMQ的库存秒杀系统设计与实现
一、秒杀场景核心挑战 瞬时高并发:万级QPS访问压力 库存准确性:避免超卖/少卖 系统可用性:防止雪崩效应 数据一致性:缓存与数据库同步 二、技术架构设计 1. 分层架构设计 用户请求│▼ 接入层(Nginx限流 令牌拦…...
hcia华为路由器静态路由实验配置
目录 一、网络拓扑分析 二、华为路由器配置(分设备) 1. R1 配置 2. R2 配置 3. R3 配置 三、验证测试 拓扑图 一、网络拓扑分析 IP 地址规划: R1:E0/0/0(12.1.1.1/24)、E0/0/1(192.168.1.…...
C语言【数据结构】:理解什么是数据结构和算法(启航)
引言 启航篇,理解什么是数据结构和算法 在 C 语言编程领域,数据结构和算法是两个核心且紧密相关的概念 一、数据结构 定义 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合(比如数组),它是组织和存储数…...
Redis7——进阶篇(五)
前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。 基础篇: Redis(一)Redis(二)Redis(三)Redis&#x…...
手写svm primal form形式
svm.py import numpy as npclass SVM:def __init__(self,C1.0,lr0.01,batch_size32,epochs100):self.CCself.lrlrself.batch_sizebatch_sizeself.epochsepochsself.wNoneself.b0.0self.epoch0#计算最高得分和对应w,bdef fit(self,X,y,X_valNone,y_valNone):sample,…...
Linux中Firewall防火墙操作
一、安装Firewall命令 yum install firewalld firewalld-config二、防火墙的基本操作 1、查看防火墙状态 使用systemctl status firewalld命令可以查看firewalld服务的状态。也可以使用firewall-cmd --state命令直接查看防火墙的状态。 2、开启防火墙 * 临时性开启&…...
【MySQL】MySQL服务器——mysqld
1.MySQL服务器 是名为 mysqld 的数据库服务器程序,和“主机”(host)不一样是一个多线程的单进程管理对磁盘和内存中数据库的访问支持并发的客户端连接支持多个存储引擎,常见的存储引擎包括InnoDB、MyISAM、Memory、Archive支持事…...
VBA+FreePic2Pdf 找出没有放入PDF组合的单个PDF工艺文件
设计部门针对某个项目做了一个工艺汇总报告,原先只要几十个工艺文件,组合成一个PDF,但后来要求要多放点PDF进去,但工艺文件都混在一起又不知道哪些是重复的,找上我让我帮忙处理一下,我开始建议让她重新再组…...
windows 下用docker 部署nginx
简单版本记录,详细内容后续再写 一、拉取nginx镜像,运行 docker pull nginx 二、创建项目目录 C:\nginx-docker\ ├── html\ │ └── index.html └── conf | └── nginx.conf// index.html<!DOCTYPE html> <html> <head&g…...
云原生性能测试全解析:如何构建高效稳定的现代应用?
一、引言 随着云计算技术的快速发展,云原生(Cloud Native)架构成为现代应用开发的主流模式。云原生应用通常采用微服务架构、容器化部署,并利用 Kubernetes(K8s)等编排工具进行管理。然而,云原…...
