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,一经查实,立即删除!

相关文章

RESTful风格接口与axios请求总结

RESTful风格接口与axios请求总结 1.GET axios.get(/api/patient/ds, {params: {pageNo: a,pageCount: b,name: app.hzQuery.name,age: app.hzQuery.age}}).then(function (response) {console.log(response);app.yyArr response.data.data.records;app.stuTotal response.d…

Linux pipe()系统调用示例

Linux系统调用pipe函数&#xff0c;创建一个pipe&#xff0c;通过传入的fd数组返回pipe的读、写两端。 其中fd[ 0 ]用于读&#xff0c;fd[ 1 ]用于写。 一个pipe是单向数据传输的&#xff0c;不用用于父子进程双向读写。创建2个pipe实现父子进程间的双线读写。 #include <u…

CSS让两个标签在同一行显示并自适应宽度

CSS让两个标签在同一行显示并自适应宽度 示例&#xff1a;svg 和 span 在同一行上并自适应宽度 使用 Flexbox 布局 HTML <div class"flex-container"><svg class"svg-icon" aria-hidden"true"><use :xlink:href"#icon-s…

0. 前言与大纲

机器学习面试题汇总与解析——前言与大纲 故事引入专栏介绍作者介绍大纲 受众&#xff1a;本教程适合于Python已经入门的学生或人士&#xff0c;有一定的编程基础。 本教程适合于算法工程师、机器学习求职的学生或人士。 故事引入 蒋 豆 芽&#xff1a;老李&#xff0c;我们…

【react hook】react hook组件中,在forEach中使用async/awati进行异步操作,为什么后面代码没有等待直接同步运行了呢?

这是因为 forEach 方法不会等待 async/await 异步操作的完成。forEach 方法是一种同步的方法&#xff0c;它会在每个迭代内部同步执行一个回调函数。当遇到 await 时&#xff0c;会立即暂停执行&#xff0c;但是 forEach 方法不会等待回调函数中的 await 异步操作完成&#xff…

php加密解密

public static function encrypt($data, $key) {$key 111;// 生成盐值$salt openssl_random_pseudo_bytes(16);// 使用盐值和密钥进行加密$encrypted openssl_encrypt($data, AES-128-CBC, $key, 0, $salt);// 将盐值和加密后的数据拼接$result base64_encode($salt . $enc…

新方向!文心一言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;编辑连接保存报错…

Mysql:RC隔离级别下如何提高并发?

RC 一、索引二、唯一索引 最近在Mysql RC隔离级别下遇到个问题:源表并发upsert目标表报错:Deadlock found when try to get lock 一、索引 Mysql是支持行锁的,但是行锁只是针对索引列,若删除条件未加索引会导致走表锁,这样就会造成死锁 二、唯一索引 索引建了之后运行还是报…

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…

淘宝天猫1688以图搜图接口,按图搜索商品,API接口调用展示(拍立淘API)

淘宝拍立淘图片搜索接口技术主要基于图像识别和内容匹配。图像识别是利用计算机视觉技术&#xff0c;对上传的图片进行特征提取和识别&#xff0c;从而找到与该图片相似的商品。内容匹配则是通过文本与图片内容的关联性&#xff0c;对商品标题、描述等信息进行匹配&#xff0c;…

Bard和ChatGPT的一些比较

Bard和ChatGPT的一些比较 2023.11.8版权声明&#xff1a;本文为博主chszs的原创文章&#xff0c;未经博主允许不得转载。 选择正确的自动文本生成工具对企业至关重要。本文将详细分析谷歌 Bard 和 ChatGPT 的优缺点&#xff0c;以帮助企业做出明智的选择。无论企业关注的是客…

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注意&…

asp.net core 获取服务实例的几种方式

在ASP.NET Core中&#xff0c;我们可以使用以下几种方式来获取服务&#xff1a; 构造函数注入&#xff08;Constructor Injection&#xff09;&#xff1a;在需要使用服务的类的构造函数中声明对应的服务类型参数&#xff0c;ASP.NET Core会自动将对应的服务实例注入进来。例如…

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

为了提升运维效率&#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;…