c++----多态(初识)

news2024/10/6 6:10:04

       大家好,今天我们来讲讲我们c++中的一个关键知识,叫做多态。但是我们学习多态之前必须将我们前面学习过的继承学习过后才能学习。当然大家可能会先想什么叫多态,我们从名字上上看的话就是多种姿态嘛。毕竟看起来这么容易理解,但其实也可以这么理解我们的多态就是多种姿态,但是有分“静”和“动”这两种多态。这里的序言我就不讲那么多了,我们的关键知识放在下面的主要知识点来讲。

多态的概览

       我们要学习多态,那么我们我们肯定要先了解什么叫做多态,是吧。那么我们先来看看比较官方的解释吧:多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态),这⾥我们重点讲运⾏时多态,编译时多态(静态多态)和运⾏时多态(动态多态)。编译时多态(静态多态)主要就是我们前⾯讲的函数重载和函数模板,他们传不同类型的参数就可以调⽤不同的函数,通过参数不同达到多种形态,之所以叫编译时多态,是因为他们实参传给形参的参数匹配是在编译时完成的,我们把编译时⼀般归为静态,运⾏时归为动态。大家看着这上面的解释我们多态就是多种结果。然后我们静态就像我们前面的重载。那么我们静态更加白话一点的话就是,我们在开始传参数的时候让我们知道走那一天大路,然后我们编译的时候根据传的参数的不同来确定我们的结果是啥。然后这就是我们的静态多态。那么动态多态就是在我们传参的时候是一样的然后我们编译的时候形式是一样的,但是我们会在运行的时候根据参数的形式或者是否符合条件然后那么得出不同的结果。

       我们来举个例子来看看:运⾏时多态,具体点就是去完成某个⾏为(函数),可以传不同的对象就会完成不同的⾏为,就达到多种形态。⽐如买票这个⾏为,当普通⼈买票时,是全价买票;学⽣买票时,是优惠买票(5折或75折);军⼈买票时是优先买票。再⽐如,同样是动物叫的⼀个⾏为(函数),传猫对象过去,就是”(>^ω^<)喵“,传狗对象过去,就是"汪汪"。我们看到上面的例子就是我们的动态多态了。是不是和我上面讲的很像啊。虽然我们传的的参数是一样的,但是具体的是不一样的。所以我们多态就是依据我们不同的参数或者条件来达到不同的效果。

多态的定义及实现

        当我们看了上面的多态的概念的时候我们就要看看如何实现了。像我们前面学习的继承。是不是我们在继承的时候有些前置条件,比如说什么要写个什么名词啊,在什么前后啊,或者什么不能改变什么东西啊。是吧。那么我们的多态当然也不能拉下啊。所以我们接下来就看看实现多态的两个必要条件

实现多态还有两个必须重要条件

        首先我们对于多态的实现的话我们要遵循下面的两个规则:(1) 必须指针或者引⽤调⽤虚函数 (2)被调⽤的函数必须是虚函数。
       当然我们这里看的话简单理解就是我们要用的都是虚函数,然后指针与引用的话最开始的那个也必须是虚函数、第二点就是我们的被调用的对象必须是虚函数,例如我们前面刚学得的继承,我们如果调用额的话就必须是虚函数。可能我这里讲的比较粗糙,我们看一下下面的解释会觉得更加稳妥一些: 要实现多态效果,第⼀必须是基类的指针或引⽤,因为只有基类的指针或引⽤才能既指向派⽣类对象;第⼆派⽣类必须对基类的虚函数重写/覆盖,重写或者覆盖了,派⽣类才能有不同的函数,多态的不同形态效果才能达到。
       然后大家看一下上面的解释和图片后。不知道大家是否对实现多态有更多的了解了。但我还是给大家稍微解释一下。我们看到左边的图片,我们可以看到这就是继承的意思。但是我们这里的继承。然后就是我们看看我们的继承与我们最普通的继承来看就是多了一行,我们普通的继承的就只有上面的那个继承的标注。但是我们这里的继承多了一行“名头”。并且我们的“名头”还是一样的。但是我这里觉不给大家详细的解释了,因为我们下面会给大家讲述的。这里就是给大家看看实现多态的两个条件。然后就是右边就是我们引用多态的方法。我们这里的test就相当于我们的主函数,然后嘞这个func就是我们实际引用多态的式子了。但是大家要思考一下的就是我们这里的多态是什么多态,是静多态还是动多态呀、依据我们前面讲过的我们的静多态含义,我们的静多态是在编译的时候就将我们要走的那一条小路确定了。我们的动多态是在运行的时候确定走那条路。那我们大家看看我们这里的是静还是动啊。是静多态,是吧。我们我们这里传参的时候就已经确定是不同的结果了。好了讲到这里我们的实现多态的两条件我想大家应该就理解的产不多了吧。

虚函数

       接下来我们要讲的就是我们实现多态的两个重要条件中的必须要存在的虚函数。而虚函数首先我们要知道什么是虚函数啊,是吧?那么我们接下来看一看虚函数的解释是什么?虚函数,是指被 virtual 关键字修饰的 成员函数。 在某基类中声明为 virtual 并在一个或多个 派生类 中被重新定义的成员函数,用法格式为: virtual 函数返回类型 函数名(参数表) {函数体};实现 多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。然后大家可以看到我们这里说了实现虚函数其实就是很简单,在我们的返回类型前面写一个virtual就可以了。但是大家可能会想,虚函数是干什么用的呢?这里其实我们就可以看出虚函数其实就是为了实现面向对象中的多态,就是为了实现我们多态。我们在上面也看到了我们的序函数很简单,就只需要写一个virtual就可以了。

      虽然说呢其实大家只需要简单的理解为虚函数是为了实现我们的多态而实现创造出来的,并且虽然说很简单,我们只需要在积累前面写一个virtual就可以了。至于我这里为什么说只需要在积累上面写一个virtual就可以了呢?因为大家我们之前说过我们这里是继承类呀,是吧?继承那么我只需要在基类写了之后,那么我的派生类是不是就直接继承下来的?所以如果依照我们上面的这个来实现的话,我们可以将其中的派生类中的virtual给删掉也是无伤大雅的。大家可以后面去自己实现一下,反正我这里是已经给大家实验过了,是可以的。然后我就不在这里表现出来了。

虚函数的重写/覆盖

       接下来我们要讲的就是我们实现多态的第二个条件中的很重要的了。重写和覆盖,我们大家可以简单理解一下重写和覆盖什么意思啊,是不是就是再写一遍或者将原来的东西给覆盖一遍?当然这里是我们自己诉说的,那么实际情况是怎么样呢?我们接下来看看官方的解释是怎么说的。虚函数的重写/覆盖:派⽣类中有⼀个跟基类完全相同的虚函数(即派⽣类虚函数与基类虚函数的返回值 类型、函数名字、参数列表完全相同),称派⽣类的虚函数重写了基类的虚函数。不知道大家看到这个后然后再看我们的第一张图片是不是觉得很符合啊。我们的派生类与基类中的函数是一样的。除了实现的内容不一样外。其他的简直就像一个翻版,当然我们的那个继承名肯定是该有区别是有区别的。

       注意:在重写基类虚函数时,派⽣类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承下来了在派⽣类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使⽤,不过在考试选择题中,经常会故意买这个坑,让你判断是否构成多态。这里我给大家再次说明了我们的派生类其实也可以不用写virtual的。然后大家可以看看下面的两个代码来实现加深一下印象:(1)第一个是我们的关于票价

class Person {
public:
virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
virtual void BuyTicket() { cout << "买票-打折" << endl; }
};
void Func(Person* ptr)
{
// 这⾥可以看到虽然都是Person指针Ptr在调⽤BuyTicket
// 但是跟ptr没关系,⽽是由ptr指向的对象决定的。
ptr->BuyTicket();
}
int main()
{
Person ps;
Student st;
Func(&ps);
Func(&st);
return 0;
}

(2):第二个是我们关于动物的叫声的

class Animal
{
public:
virtual void talk() const
{}
};
class Dog : public Animal
{
public:
virtual void talk() const
{
std::cout << "汪汪" << std::endl;
}
};
class Cat : public Animal
{
public:
virtual void talk() const
{
std::cout << "(>^ω^<)喵" << std::endl;
}
};
void letsHear(const Animal& animal)
{
animal.talk();
}
int main()
{
Cat cat;
Dog dog;
letsHear(cat);
letsHear(dog);
return 0;
}

      我想当大家看了上面的两个例子之后,其实对我们的多态的实现和一些简单的定义应该已经了解的差不多了,如果大家还感兴趣的话,可以先看一下我们下面的一个题目。这个题目可不简单呀,大家要多思考一下,因为这是有一个很坑的很多面试题都在使用的,大家可以看一下下面的题,然后呢我会先将答案给大家。这道题选 B:我想大多数的朋友会选择D,包括我们开始也是选着的D,但是最后看了讲解后才发现应该选着B的。这可是一道面试题哦。大家想想要是在面试的时候看到这么一道题,原本是信心满满的但是后面一看发现选错了,会不会很气啊,所以我这里就想和大家打个预防针。想让大家体验一下社会的险恶。然后我在下一篇关于多态的博客中再给大家解释说明。

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

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

相关文章

服务器conda环境安装rpy2

参考博客 https://stackoverflow.com/questions/68936589/how-to-select-r-installation-when-using-rpy2-on-conda 现在我遇到这样一个问题&#xff0c;服务器系统环境没有R(没有权限安装&#xff09;&#xff0c;我只能在minconda的conda环境中使用R, 使用方法如下 我现在…

Rocky Linux 9搭建K8s-1.28.0+docker一主多从集群测试环境

集群类型&#xff1a; Kubernetes集群大体上分为两类&#xff1a;一主多从和多主多从 一主多从&#xff1a;一台master节点和多台node节点&#xff0c;搭建简单&#xff0c;但是有单机故障风险&#xff0c;适用于测试环境 多主多从&#xff1a;多台master节点和多台node节点&am…

ELK日志收集之ES的DSL查询语句

一、简介 在Elasticsearch中&#xff0c;我们可以使用Elasticsearch-DSL(Elasticsearch Domain Specific Language)来构建和执行复杂的搜索查询。官方Query DSL指导文档。 叶查询&#xff1a;在特定字段中寻找特定值,例如 match ,term 或 range。 复合查询&#xff1a;具有查询…

【进阶OpenCV】 (5)--指纹验证

文章目录 指纹验证1. 验证原理2. 读取图片3. 计算特征匹配点 总结 指纹验证 指纹验证基于人类指纹的独特性和稳定性。每个人的指纹在图案、断点和交叉点上各不相同&#xff0c;这种唯一性和终生不变性使得指纹成为身份验证的可靠手段。指纹识别技术通过采集和分析指纹图像&…

39 C 语言枚举类型、枚举常量、枚举变量、枚举的遍历、枚举数组、枚举与 switch

目录 1 什么是枚举 2 定义枚举类型 2.1 语法格式 2.2 枚举元素的特点 2.3 案例演示 3 枚举变量 3.1 什么是枚举变量 3.2 定义枚举变量的多种方式 3.3 案例演示 1&#xff1a;标准版枚举类型 3.4 案例演示 2&#xff1a;简化版枚举类型 3.5 案例演示 3&#xff1a;匿…

【教学类-77-01】20241005青花瓷立体书

背景需求&#xff1a; 今天翻到小红书上一个青花瓷立体书 &#x1f1ed;&#x1f1f0;香港免费展览&#xff5c;青花瓷立体纸艺观展册&#x1f4d6; - 小红书 (xiaohongshu.com)https://www.xiaohongshu.com/discovery/item/6426a8fb000000001303653e?app_platformandroid&a…

买卖股票大合集

刷题刷题往死里刷。 121. 买卖股票的最佳时机 链接 121. 买卖股票的最佳时机 思路&#xff1a; 二次做所以有思路了&#xff0c; 从头遍历数组&#xff0c;维持一个最小值&#xff0c;且遇到一个值就计算差值&#xff0c;且维护这个最大值为答案。 class Solution {public …

文心智能体——制作你的专属AI

随着社会的进步和互联网技术的发展&#xff0c;人工智能领域正蓬勃发展。最近几年关于人工智能的新闻日渐增多并且成为了当代最大的热点&#xff0c;所有的领域都在引进AI、训练AI、使用AI&#xff0c;AI正逐步融入人们的生活。从前几年chatGPT大语言模型的横空出世&#xff0c…

【CSDN入门级教程】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

Linux进程调度和进程切换

并行&#xff08;Parallel&#xff09; 含义&#xff1a;并行是指多个任务在同一时刻同时执行。 硬件要求&#xff1a;需要多个处理器&#xff08;如多核CPU&#xff09;或者多台计算设备来实现&#xff0c;这些执行单元能够真正地同时处理不同的任务。例如&#xff0c;一个具…

vite学习教程05、vite+vue2构建本地 SVG 图标

文章目录 前言一、构建本地SVG图标详细步骤1、安装开发依赖2、配置vite2.1、配置vite.config.js2.2、封装vite引入插件脚本 解决报错&#xff1a;can not find package fast-glob imported 二、实际应用应用1&#xff1a;未封装&#xff0c;直接vue应用应用2&#xff1a;封装vu…

Self-Operating Computer:基于PyAutoGui加AI实现无人“驾驶“电脑,让Python带你走近未来世界

近年来&#xff0c;AI 领域不断取得突破&#xff0c;特别是多模态模型的出现&#xff0c;为计算机无人操控带来了全新的可能性。 想象一下&#xff0c;你的电脑不再需要你手动操作&#xff0c;而是可以像人一样&#xff0c;理解你的指令&#xff0c;并自动执行一系列鼠标键盘操…

【word脚注】双栏设置word脚注,脚注仅位于左栏,右栏不留白

【word脚注】双栏设置word脚注&#xff0c;脚注仅位于左栏&#xff0c;右栏不留白 调整前效果解决方法调整后效果参考文献 调整前效果 调整前&#xff1a;脚注位于左下角&#xff0c;但右栏与左栏内容对其&#xff0c;未填充右下角的空白区域 解决方法 备份源文件复制脚注内…

MySQL--聚合查询、联合查询、子查询、合并查询(上万字超详解!!!)

目录 一、前言二、聚合查询2.1 聚合函数2.1.1 COUNT():统计所有行2.1.2 SUM(列名) 求和2.1.3 AVG()2.1.4 MAX()、MIN() 2.2 GROUP BY子句&#xff08;分组查询&#xff09;2.3 HAVING 三、联合查询3.1表的笛卡儿积3.2内连接3.2.1 例题一3.2.2 例题二 3.3外连接3.3.1 右外连接3.…

【每天学个新注解】Day 16 Lombok注解简解(十五)—@FieldNameConstants

FieldNameConstants 根据属性名生成常量类的常量。 1、如何使用 加在需要根据属性名生成常量的属性上。 2、代码示例 例&#xff1a; FieldNameConstants public class Test {private String iAmAField;private int andSoAmI;FieldNameConstants.Exclude private int asA…

Microsoft AI部门的CEO额备忘录

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

kafka-windows集群部署

kafka-windows集群部署目录 文章目录 kafka-windows集群部署目录前言一、复制出来四个kafka文件夹二、修改集群每个kafka的配置文件四、启动zookeeper&#xff0c;kafka集群 前言 部署本文步骤可以先阅读这一篇博客&#xff0c;这篇是关于单机kafka部署测试的。本文用到的文件…

VUE2常见问题以及解决方案汇总(不断更新中)

解决vue项目中 el-table 的 row-click 事件与行内点击事件冲突&#xff0c;点击事件不生效&#xff08;表格行点击事件和行内元素点击事件冲突&#xff09;需要阻止事件冒泡 问题描述 1.点击列的编辑按钮&#xff0c;会触发按钮本身事件&#xff0c;同时会触发行点击事件 2.点…

自用Proteus(8.15)常用元器件图示和功能介绍(持续更新...)

文章目录 一、 前言二、新建工程&#xff08;以51单片机流水灯为例&#xff09;2.1 打开软件2.2 建立新工程2.3 创建原理图2.4 不创建PCB布版设计2.5 创建成功2.6 添加元器件2.7 原理图放置完成2.8 编写程序&#xff0c;进行仿真2.9 仿真 三、常用元器件图示和功能介绍3.1 元件…

春秋云镜靶场之CVE-2022-28525

1.环境搭建 我们开启环境 可以看到题目提示我们是文件上传漏洞&#xff0c;那么我们就进行测试 2.开启环境 我们开启环境&#xff0c;可以看到是一个登录页面&#xff0c;登录页面:一种是弱口令&#xff0c;一种是自己进行注册&#xff0c;一种是SQL注入&#xff0c;一种是在…