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

       大家好,今天我们来讲讲我们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.rhkb.cn/news/439811.html

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

相关文章

【Verilog学习日常】—牛客网刷题—Verilog进阶挑战—VL25

输入序列连续的序列检测 描述 请编写一个序列检测模块&#xff0c;检测输入信号a是否满足01110001序列&#xff0c;当信号满足该序列&#xff0c;给出指示信号match。 模块的接口信号图如下&#xff1a; 模块的时序图如下&#xff1a; 请使用Verilog HDL实现以上功能&#x…

设置服务器走本地代理

勾选&#xff1a; 然后&#xff1a; git clone https://github.com/rofl0r/proxychains-ng.git./configure --prefix/home/wangguisen/usr --sysconfdir/home/wangguisen/etcmakemake install# 在最后配置成本地代理地址 vim /home/wangguisen/etc/proxychains.confsocks4 17…

基于基于微信小程序的社区订餐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

macos安装mongodb

文章目录 说明安装和配置安装mongodb配置PATH变量 验证日志及数据存放目录 mac启动和关闭mongodb后台启动失败问题mongodb-compass(GUI) 说明 Homebrew core 列表目前已经将 MongoDB 移除,不再为其提供支持。但是使用国内镜像的brew还是可以安装的&#xff01;这里直接从官网下…

算法笔记(四)——模拟

算法笔记&#xff08;四&#xff09;——模拟 文章目录 算法笔记&#xff08;四&#xff09;——模拟替换所有的问号提莫攻击Z字形变换外观数列数青蛙 模拟算法就是根据题目的要求&#xff0c;题目让干神马就做神马&#xff0c;一步一步来 替换所有的问号 题目&#xff1a;替换…

Tableau数据可视化入门

目录 一、实验名称 二、实验目的 三、实验原理 四、实验环境 五、实验步骤 1、Tableau界面引导 2、数据来源 3、数据预处理操作 4、制作中国各个地区的利润图表 4.1条形图 4.2气泡图 5、制作填充地球图 一、实验名称&#xff1a; 实验一&#xff1a;Tableau数据可…

探索 GraphRAG:从存储到查询,深入解析 NebulaGraph 与传统 SQL 的对比

近年来&#xff0c;图数据库逐渐成为大数据和人工智能领域的热议话题。特别是随着 GraphRAG 技术的火爆&#xff0c;如何高效存储和查询大规模图数据成为很多开发者关心的问题。出于好奇&#xff0c;我最近尝试了 GraphRAG 并研究其存储结构&#xff0c;因此决定进一步探索图数…

初识算法 · 双指针(2)

目录 前言&#xff1a; 盛最多水的容器 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 有效三角形的个数 题目解析&#xff1a; 算法原理&#xff1a; 算法编写&#xff1a; 前言&#xff1a; 本文介绍两个题目&#xff0c;盛最多水的容器和有效三…

C语言复习概要(三)

本文 使用Visual Studio进行调试的技巧与函数递归详解1. 引言2. Visual Studio 调试技巧2.1. 断点的使用2.1.1. 基本断点示例&#xff1a;设置基本断点 2.1.2. 条件断点示例&#xff1a;条件断点 2.2. 逐步执行代码示例&#xff1a;逐步执行代码 2.3. 监视变量使用监视窗口 2.4…

第十一章 缓存

目录 一、什么是缓存 二、缓存更新策略 2.1. 缓存主动更新策略 2.1.1. Cache Aside模式&#xff08;主流&#xff09;‌ 2.1.2. Read/Write Through模式‌ 2.1‌.3. Write Behind模式‌ 2.1.4. 总结 三、缓存穿透 四、缓存雪崩 五、缓存击穿 本文中的图片内容部分来源…

训练验证器解决数学应用题

人工智能咨询培训老师叶梓 转载标明出处 数学问题解决不仅要求模型能够理解问题的语言表述&#xff0c;还要求其能够准确地执行一系列数学运算&#xff0c;每一步的准确性都至关重要。遗憾的是&#xff0c;现有的语言模型在这一领域的性能远远未能达到人类的水平&#xff0c;它…

【Python|接口自动化测试】使用requests发送http请求时添加headers

文章目录 1.前言2.HTTP请求头的作用3.在不添加headers时4.反爬虫是什么&#xff1f;5.在请求时添加headers 1.前言 本篇文章主要讲解如何使用requests请求时添加headers&#xff0c;为什么要加headers呢&#xff1f;是因为有些接口不添加headers时&#xff0c;请求会失败。 2…

Windows上 minGW64 编译 libssh2库

下载libssh2库:https://libssh2.org/download/libssh2-1.11.0.zip 继续下载OpenSSL库: https://codeload.github.com/openssl/openssl/zip/refs/heads/OpenSSL_1_0_2-stable

java中创建不可变集合

一.应用场景 二.创建不可变集合的书写格式&#xff08;List&#xff0c;Set&#xff0c;Map) List集合 package com.njau.d9_immutable;import java.util.Iterator; import java.util.List;/*** 创建不可变集合:List.of()方法* "张三","李四","王五…

SpringBoot中间件Docker

Docker&#xff08;属于C/S架构软件&#xff09; 简介与概述 1.Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux …

登 Nature 子刊!论文一作详解蛋白质语言模型的小样本学习方法,解决湿实验数据匮乏难题

在「Meet AI4S」系列直播第三期中&#xff0c;我们有幸邀请到了上海交通大学自然科学研究院 & 上海国家应用数学中心博士后周子宜&#xff0c; 他所在的上海交通大学洪亮课题组研究方向主要为 AI 蛋白和药物设计、分子生物物理。该课题组研究成果颇丰&#xff0c;截止目前共…

【AI副业项目】揭密AI技术对于儿童古诗文项目的应用

大家都知道&#xff0c;古诗文作为中华文化的瑰宝&#xff0c;承载着丰富的历史情感和智慧。但是&#xff0c;在现代社会快节奏的生活中&#xff0c;如何让更多人尤其是少年儿童感受到古诗文的魅力&#xff0c;成为了一个极需解决的问题。 AI技术的兴起为这一难题提供了新的解…

【D3.js in Action 3 精译_025】3.4 让 D3 数据适应屏幕(中)—— 线性比例尺的用法

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…

【Python】Streamlit:为数据科学与机器学习打造的简易应用框架

Streamlit 是一个开源的 Python 库&#xff0c;专为数据科学家和机器学习开发者设计&#xff0c;旨在快速构建数据应用。通过简单的 Python 脚本&#xff0c;开发者无需掌握前端技术&#xff0c;即可将数据分析和模型结果转化为直观、交互式的 Web 应用。其简洁的 API 设计使得…

MATLAB下的RSSI定位程序,二维平面上的定位,基站数量可自适应

文章目录 引言程序概述程序代码运行结果待定位点、锚点、计算结果显示待定位点和计算结果坐标 引言 随着无线通信技术的发展&#xff0c;基于 R S S I RSSI RSSI&#xff08;接收信号强度指示&#xff09;的方法在定位系统中变得越来越流行。 R S S I RSSI RSSI定位技术特别适…