C++多态特性

在这里插入图片描述

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻强烈推荐优质专栏: 🍔🍟🌯C++的世界(持续更新中)
🐻推荐专栏1: 🍔🍟🌯C语言初阶
🐻推荐专栏2: 🍔🍟🌯C语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:讲解C++中多态知识,不同对象不同的处理方式.
金句分享:
✨不要总是抱怨环境,鼓起勇气战胜它!✨

前言

多态的概念:就是多种形态,当不同的对象去完成某个动作时会产生出不同的状态。

比如:在现实生活中,我们经常遇到不同身份的人享受的待遇不一样.

购买回家的火车票时,如果是购买的学生票,会有打折优惠.
在参加某宝,某团的活动时,新用户获得的优惠券就会比活跃用户的额度高不少.

C++中的多态(polymorphism)指的是同一个函数名在不同对象上可以有不同的行为。
它可以通过两种方式实现:
(1)虚函数(virtual function

虚函数是在基类中声明的函数,它可以被派生类重写,实现多态的效果。在派生类中实现的函数可以覆盖基类中的同名函数,而且会在运行时的对象类型上调用合适的函数。通过将基类指针或引用指向派生类对象,可以实现动态多态性。

(2)模板(template)。(前面已经讲过了)

模板是一种通用的代码库,可以为不同的类型提供相同的代码实现。使用模板可以实现静态多态性。在编译期间,编译器会依据模板中使用的类型,生成适当的代码。

使用多态可以让代码更加灵活,易于维护和扩展。此外,多态也是对象导向程序设计中的核心概念之一。

目录

  • 前言
  • 一、多态的实现
    • 🍭实现多态的条件:
  • 二、何为虚函数?
    • 🍉就你小子特殊?
    • 2.1 析构函数可以是虚函数吗?
  • 三、 关键字override 和 final

一、多态的实现

代码1,2,3的执行结果是什么?

class People
{
public:void Have_lunch(){cout << "你需要支付10元的午餐费!" << endl;}
};class Student:public People
{
public:void Have_lunch(){cout << "你需要支付8元的午餐费!" << endl;}
};class Teacher:public People
{
public:void Have_lunch(){cout << "老师,您好,欢迎就餐!已扣除5元餐费." << endl;}
};void test1(People& p1)
{p1.Have_lunch();
}int main()
{People p1;Student s1;Teacher t1;test1(p1);	//1test1(s1);	//2test1(t1);	//3return 0;
}

在这里插入图片描述
运行结果:

你需要支付10元的午餐费!
你需要支付10元的午餐费!
你需要支付10元的午餐费!

在前面的继承章节,我们知道,基类和派生类是两个不同的作用域,定义同名的两个函数时,会形成隐藏操作.所以这里的打印结果都是一样的.

如果想实现态,也就是不同的对象调用同一个函数,实现不同的结果,以下代码就是实现的例子,试着观察一下区别吧.
在这里插入图片描述

运行结果:

你需要支付10元的午餐费!
你需要支付8元的午餐费!
老师,您好,欢迎就餐!已扣除5元餐费.

🍭实现多态的条件:

  1. 继承关系:多态需要通过继承关系来实现,子类必须要继承父类。

  2. 方法重写(虚函数实现):子类必须重写父类的方法,这样才能表现出不同的行为。

  3. 父类指针/引用指向子类对象:必须是父类的指针或者引用调用虚函数,才能进行多态操作。

二、何为虚函数?

C++中的虚函数是一种特殊的成员函数,用于在继承关系中实现多态性。在父类中通过关键字virtual声明的函数为虚函数,子类可以覆盖并重新实现(重写)该函数。当通过父类的指针或引用调用虚函数时,实际调用的是子类中的实现,而不是父类的实现。这样就实现了多态.

普通函数:

	virtual void Have_lunch(){cout << "你需要支付8元的午餐费!" << endl;}

虚函数:

	virtual void Have_lunch(){cout << "你需要支付8元的午餐费!" << endl;}

虚函数的重写要求十分严格:

  1. 返回类型要相同:
    在这里插入图片描述
  2. 参数类型要相同:
    在这里插入图片描述
  3. 函数名相同:这个就不演示了,肯定无法实现多态.

🍉就你小子特殊?

虚函数的特殊情况: 斜变

派生类重写基类虚函数时,与基类虚函数返回值类型不同。
基类虚函数返回基类对象的指针或者引用.
派生类虚函数返回派生类对象的指针或者引用时.
这种情况,即使返回值不同,此时也满足虚函数的重写,也可以实现多态.

//斜变
class People
{
public:virtual People* Have_lunch()		//返回基类的指针或者引用{cout << "你需要支付10元的午餐费!" << endl;return nullptr;}
};class Student :public People
{
public:virtual Student* Have_lunch()		//返回派生类的指针或者引用{cout << "你需要支付8元的午餐费!" << endl;return nullptr;}
};class Teacher :public People
{
public:virtual Teacher* Have_lunch()		/返回派生类的指针或者引用{cout << "老师,您好,欢迎就餐!已扣除5元餐费." << endl;return nullptr;}
};

运行结果:
在这里插入图片描述

2.1 析构函数可以是虚函数吗?

显然,基类与派生类析构函数的名字不同 .

看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。即所有对象的析构函数,在编译后,都被处理为统一的名字:destructor.

在这里插入图片描述

  1. 为什么析构函数名要被统一转化为destructor?

因为要实现多态需要函数名相同.

  1. 为什么析构函数要实现多态?

因为析构函数实现多态了以后,才能实现在析构基类和派生类时,各自调用自己的析构函数,防止内存泄漏!

示例:

class People
{
public:~People(){free(arr);cout << "~People()" << endl;}
private:int* arr = new int[10];		
};class Student :public People
{
public:~Student(){free(arr2);cout << "~Student()" << endl;}
private:int* arr2 = new int[10];
};int main()
{People* p1 = new People;		People* p2 = new Student;		//基类指针指向派生类delete p1;delete p2;		//arr2未释放return 0;
}

运行结果:

在这里插入图片描述
显然,在未实现多态的情况下,当基类指针指向派生类时,调用析构函数都只能调用基类的析构函数.这就导致了派生类存在成员变量并没有释放空间,也就导致了内存泄漏!

在这里插入图片描述
综上,析构函数可以是虚函数,而且还强烈建议将析构函数写成虚函数,实现多态.

虚函数重写需要遵守以下条件:

  1. 函数名称、参数列表和返回类型在父类和子类中必须完全相同。(三同)
  2. 函数在父类中必须被声明为virtual关键字,否则在子类中重写将不会产生多态效果。
  3. 函数在子类中必须使用virtual关键字进行声明,以便在运行时确定需要调用的是哪个版本的函数。

三、 关键字override 和 final

先声明一下:
这两个关键字是c++11才出现的,老版本不支持哦!

(1) override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。

很多时候,我们需要实现多态,但是由于一时疏忽,将函数名写错了一个字母,或者返回值,参数列表等不同,而导致无法进行虚函数的重写.

class People
{
public:virtual void Have_lunch(){cout << "你需要支付10元的午餐费!" << endl;}
};class Student :public People
{
public:virtual void Have_Lunch()override{cout << "你需要支付8元的午餐费!" << endl;}
};class Teacher :public People
{
public:void Have_lunch()override{cout << "老师,您好,欢迎就餐!已扣除5元餐费." << endl;}
};

在这里插入图片描述

有的时候,我们并不像函数成为虚函数,又担心自己不小心满足了虚函数的重写的条件.(其实,博主感觉这种情况很少,也可能是博主目前接触的代码还比较少,没体会到.😂)

(2) final:修饰虚函数,表示该虚函数不能再被重写.

class People
{
public:virtual void Have_lunch()final{cout << "你需要支付10元的午餐费!" << endl;}
};class Student :public People
{
public:virtual void Have_lunch(){cout << "你需要支付8元的午餐费!" << endl;}
};

在这里插入图片描述

对于多态,本文就介绍到这里了,多态的实现原理是什么?菱形继承搭配虚拟继承会不会很头痛?
想要更加深层的理解C++的多态,下一篇文章,咱们不见不散!
在这里插入图片描述

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

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

相关文章

新方向!文心一言X具身智能,用LLM大模型驱动智能小车

具身智能已成为近年来研究的热点领域之一。具身智能强调将智能体与实体环境相结合&#xff0c;通过智能体与环境的交互&#xff0c;来感知和理解世界&#xff0c;最终实现在真实环境中的自主决策和运动控制。 如何基于文心大模型&#xff0c;低成本入门“具身智能”&#xff0…

YOLOv8模型ONNX格式INT8量化轻松搞定

ONNX格式模型量化 深度学习模型量化支持深度学习模型部署框架支持的一种轻量化模型与加速模型推理的一种常用手段&#xff0c;ONNXRUNTIME支持模型的简化、量化等脚本操作&#xff0c;简单易学&#xff0c;非常实用。 ONNX 模型量化常见的量化方法有三种&#xff1a;动态量化…

刚安装的MySQL使用Navicat操作数据库遇到的问题

刚安装的MySQL使用Navicat操作数据库遇到的问题 一、编辑连接保存报错二、打开数据表很慢三、MySQL的进程出现大量“sleep”状态的进程四、执行sql脚本报错&#xff0c;部分表导不进去五、当前MySQL配置文件 一、编辑连接保存报错 连接上了数据库&#xff0c;编辑连接保存报错…

Linux下内网穿透实现云原生观测分析工具的远程访问

&#x1f4d1;前言 本文主要是Linux下内网穿透实现云原生观测分析工具的远程访问设置的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &…

Peter算法小课堂—八皇后问题

独立集问题&#xff1a;安排互不冲突的个体 四个斜眼枪手 bool valid(int x,int y){for(int i1;i<min(x,y);i)if(f[x-i][y-i]) return 0;for(int i1;i<min(x,N-1-y);i)if(f[x-i][yi]) return 0;return 1; } void dfs(int x,int y,int c){if(cGUNS){ans;print();return;}i…

django|报错SQLite 3.8.3 or later is required的解决方案

迁移原同事写的程序&#xff0c;到新服务器上边。运行报错。解决方案有三种 降低django版本升级sqlite3&#xff0c;不低于3.8.3版本修改django源码 方案一、降低django版本 卸载高版本django pip uninstall django安装低版本&#xff0c;如 pip install django2.1.7注意&…

贝锐蒲公英智慧运维方案:实现远程网络监控、管理、维护工业设备

为了提升运维效率&#xff0c;能够及时发现和响应设备的故障、异常和潜在问题。 越来越多的企业都在搭建“集中式”的远程智慧运维体系&#xff0c;以提高运维效率和降低成本。 但是&#xff0c;受限于网络&#xff0c;将不同地域的资源和信息进行整合&#xff0c;实现统一管理…

招聘信息采集

首先&#xff0c;我们需要使用PHP的curl库来发送HTTP请求。以下是一个基本的示例&#xff1a; <?php // 初始化curl $ch curl_init();// 设置代理 curl_setopt($ch, CURLOPT_PROXY, "jshk.com.cn");// 设置URL curl_setopt($ch, CURLOPT_URL, "http://www…

linuxC语言缓冲区及小程序的实现

文章目录 1.文件缓冲区1.1介绍1.2缓冲文件系统1.3冲刷函数fflush1.4认识linux下的缓冲区 2.linux小程序的实现2.1 回车\r和换行\n2.2倒计时程序2.3进度条小程序sleep/usleep代码运行结果 1.文件缓冲区 1.1介绍 为缓和 CPU 与 I/O 设备之间速度不匹配&#xff0c;文件缓冲区用以…

2023最新版本 从零基础入门C++与QT(学习笔记) -1- C++输入与输出

&#x1f38f;说在前面 &#x1f388;我预计是使用两个月的时间玩转C与QT &#x1f388;所以这是一篇学习笔记 &#x1f388;根据学习的效率可能提前完成学习,加油&#xff01;&#xff01;&#xff01; 输入(代码如下方代码块) &#x1f384;分析一下构成 &#x1f388;…

HTML页面模拟了一个类似Excel的表格在线diy修改表格内容

html实现在线表格编辑&#xff0c;可以修改每个表格内容&#xff0c;并且可以添加行和列 这个HTML页面模拟了一个类似Excel的表格&#xff0c;可以添加和删除行和列&#xff0c;并且可以编辑每个表格的内容。通过点击按钮可以添加新的行和列&#xff0c;通过按钮可以删除最后一…

关灯游戏及扩展

7.8 图形界面应用案例——关灯游戏 题目&#xff1a; [案例]游戏初步——关灯游戏。 关灯游戏是很有意思的益智游戏&#xff0c;玩家通过单击关掉(或打开)一盏灯。如果关(掉&#xff08;或打开)一个电灯&#xff0c;其周围(上下左右)的电灯也会触及开关&#xff0c;成…

JSON可视化管理工具JSON Hero

本文软件由网友 zxc 推荐&#xff1b; 什么是 JSON Hero &#xff1f; JSON Hero 是一个简单实用的 JSON 工具&#xff0c;通过简介美观的 UI 及增强的额外功能&#xff0c;使得阅读和理解 JSON 文档变得更容易、直观。 主要功能 支持多种视图以便查看 JSON&#xff1a;列视图…

css:clip元素裁剪实现Loading加载效果边框

clip 属性定义了元素的哪一部分是可见的。clip 属性只适用于 position:absolute 的元素。 警告&#xff1a; 这个属性已被废弃。建议使用 clip-path 文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/cliphttps://developer.mozilla.org/zh-CN/docs/Web/CSS/clip-path …

Linux安装MySQL8.0服务

Linux安装MySQL8.0服务 文章目录 Linux安装MySQL8.0服务一、卸载1.1 查看mariadb1.2 卸载 二、安装2.1 下载2.2 上传2.3 解压2.4 重命名2.5 删除2.6 创建目录2.7 环境变量2.8 修改配置2.9 配置文件2.9 用户与用户组2.10 初始化2.11 其它 三、开启远程连接MySQL 一、卸载 首先第…

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【postgresql】CentOS7 安装pgAdmin 4

CentOS7 安装PostgreSQL Web管理工具pgAdmin 4。 pgAdmin 是世界上最先进的开源数据库 PostgreSQL 最受欢迎且功能丰富的开源管理和开发平台。 下载地址&#xff1a; pgadmin-4 download pgAdmin 4分为桌面版和服务器版。 我们这里部署服务器版本。 安装RPM包。 安装源 s…

现在学编程还能够月薪过万吗?

当我们谈到职业选择时&#xff0c;一项常受人关注的问题是&#xff0c;现在学编程还能月薪过万吗&#xff1f;这似乎是一个不断挂在年轻人嘴边的问题&#xff0c;尤其是在数字化时代&#xff0c;编程的需求越来越大。 所以今天让我们一起探讨这个问题&#xff0c;看看现实生活…

汽车标定技术(九)--标定常量与#pragma的趣事

目录 1. 不添加#pragma语句 2. 添加#pragma语句 3. 标定量只给flash空间&#xff0c;不给ram指定空间 4. 总结 在之前不会使用overlay机制的时候&#xff0c;我们想要做汽车标定&#xff0c;标定常量编译出来的地址一般都应该是ram的地址&#xff0c;而且在链接文件中都会指…

6.5对称二叉树(LC101-E)

算法&#xff1a; 其实就是比较左右子树是否可以翻转 比较的时候&#xff1a; 比较外面的节点是否相等&#xff0c;如示例1中的节点3 比较里面的节点是否相等&#xff0c;如示例1中的节点4 基本思路是这样的&#xff0c;那怎么遍历呢&#xff1f; 二叉树的题一定要掌握到…