【C++】多态的使用详解

本篇要分享的内容是多态,以下为本篇目录。

目录

1.多态的概念

2. 多态的定义及实现

3.虚函数

4.C++11  override和final

4.1final关键字

4.2override关键字

 5.抽象类

5.1抽象类的概念

5.2接口继承和实现继承


1.多态的概念

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态。

比如旅行景点的成人票是全票,儿童半票,军人优先购票;

又比如拼多多的红包,新用户就会获得很多福利;而老用户的红包福利只有一点点。

像这样不同的身份可以产生不同的行为和结果,也是一种多态行为。

2. 多态的定义及实现

用一段简单的代码来认识多态

#include<iostream>
using namespace std;
class Person 
{
public:
	virtual void BuyTicket() 
	{ 
		cout << "买票-全价" << endl;
	}
};
class Student : public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票-半价" << endl;
	}
};

void Func(Person& p)
{
	p.BuyTicket();
}
int main()
{
	Person ps;
	Student st;
	Func(ps);
	Func(st);
	return 0;
}

可以看到在多态中引入了一个新的概念: 虚函数(即在函数前加上virtual)。

并且在函数测试中使用父类创建了对象,并且调用函数,这时要注意我们在main函数中分别用父类和子类创建了对象,并调用了Func函数。

在之前的继承中我们知道,父类的引用即可传父类对象,也可以传子类对象

这时运行代码观察结果

 

可以看到这里调用了两个函数:
普通人买票全价,学生买票半价;

但是当我们将切片改为传值传参,而不是传引用传参时结果就会调用同一个函数

可以看到这里去掉了&符号

运行结果如下

可以看到调用到的时一个函数

那这就证明出形成多态的条件:

①.虚函数重写

②.父类的指针或者函数去调用虚函数

以上条件只要有一个不满足,就会变成普通调用,就会去看对象的类型

3.虚函数

在之前的继承中我们学到过虚继承的关键字也是virtual,但是和我们今天在多态中所学的虚函数是没有关系的,如同取地址符号&,和引用符号&,虽然符号相同,但是是有区别的。

要构建多态的第一个条件就是构成虚函数重写,那么构成虚函数重写也是有条件的:

继承关系中两个父子类关系的虚函数,函数名、参数、返回值,都要相同,才能完成虚函数的重写。

当然,virtual只能修饰成员函数,它的作用是修饰成员函数来构成多态,在类外使用当然是会直接报错的。

但是上述的三同(函数名、参数、返回值相同)又有一个例外,称之为协变:返回值可以不同,但是必须是父子类关系的指针或引用

如图

可以看到我们修改了函数的返回值是父子关系类的指针,结果也会构成多态。

但是在如上的这中情况下,子类又可以不加virtual

为什么要这样设计呢?

这里的函数需要重写,重写就是重复实现,也可以认为在父类中的虚函数,子类与父类同名的虚函数virtual也会继承下来。

以上的两种特殊用法是需要记忆的,是可以使用,但是在我们自己编写代码中最好还是使用三同来完成多态。

接下来则是析构函数,有如下场景

class Person {
public:
	~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
	 ~Student() { cout << "~Student()" << endl; }
};
int main()
{
	Person* p1 = new Person;
	delete p1;

	Person* p2 = new Student;
	delete p2;
	return 0;
}

这里的分别在两个类中定义了两个析构函数,为方便观察我们输出他们。

再在main函数中分别定义两个指针,并且分别指向父类和子类并析构

运行结果如下 

 可以看到创建的两个指针指向的类不同,但是却同时调用了父类的析构函数,原因是在没有使用virtual修饰函数的情况下,所有的析构函数都被编译器命名为:destroy(),所以在两个不同的类中相当与重写了析构函数。

因为子类不能正常调用析构函数,所以有可能会造成内存泄漏。

 所以我们需要使用虚函数就可以使他们分别调用自己类中的析构函数

(子类调用析构函数是先子后父)。

4.C++11  override和final

在C++11中更新了两个关键字final和override;

4.1final关键字

1.final修饰类时,这个类不能被继承

2.final修饰虚函数时,这个虚函数不能被重写

用法如下

class Car
{
public:
	virtual void Drive() final {}
};
class Benz :public Car
{
public:
	virtual void Drive() { cout << "Benz-舒适" << endl; }
};

此处实在Car类中的虚函数后加上final {};

 可以看到使用final之后,这个虚函数就不能被重写了

并且这个函数必须是虚函数

 这里报错很明显,final不能修饰非虚函数。

在Car类后加上final之后这个类就不能被继承了 。

4.2override关键字

override用来修饰派生类的虚函数,用来检测是否完成重写。

以下是override的使用位置

class Car
{
	public:
		virtual void Drive()
		{}
};

class Benz :public Car
{
	public:
	virtual void Drive() override {cout << "Benz-舒适" << endl;}
};

如果没有完成重写就会报错

虚函数一定是要重写的,否则虚函数是没有意义的。

 5.抽象类

5.1抽象类的概念

上面我们提到过虚函数。在虚函数后面加上=0,则这个函数为纯虚函数

那么此时,包含整个纯虚函数的类叫做抽象类,也叫做接口类,抽象类不能实例化对象。 

可以看到上图的Car中有纯虚函数,Car就变成了抽象类,此时Car也就不能定义对象,但是可以定义指针。

 

上图中我们定义了新的类,并且继承了抽象类Car,可以看到此时新的类也不能实例化对象了; 

但是我们可以将纯虚函数重写,这样就可以实例化对象了

所以有以下使用场景

class Car
{
public:
	virtual void Drive() = 0;
};

class Benz :public Car
{
public:
	void Drive()
	{
		cout << "Benz" << endl;
	}
};

class BMW :public Car
{
public:
	virtual void Drive()
	{
		cout << "BMW-操控" << endl;
	}
};

void func(Car* c)
{
	c->Drive();
}
int main()
{
	func(new Benz);
	func(new BMW);
/*Car* pBenz = new Benz;
pBenz->Drive();
Car* pBMW = new BMW;
pBMW->Drive();*/
}

在以上代码中我们发现在func函数中的参数定义了抽象类的指针对象c,利用c去调用类中重写的函数。

同时在main函数中调用函数,不难看出指向哪个子类就调用的是哪个子类重写的函数。

所以我们可以得出的结论是抽象类强制了子类去重写。

5.2接口继承和实现继承

普通函数的继承是一种实现继承

虚函数的继承是一种接口继承

用代码说明

首先是实现继承,我们在父类中简单写了一个输出函数,他会直接继承到子类中,也就是说子类可以直接对func函数直接进行调用,可以理解为一种函数的复用。

而虚函数的接口继承,相当于需要在子类中重写函数的实现,但是调用的参数,或者说是接口,还是父类的接口,所以我们才需要重写虚函数。

最后用一道小题来了解接口继承

class A
 {
 public:
   virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
   virtual void test(){ func();}
 };
 class B : public A
 {
 public:
   void func(int val=0){ std::cout<<"B->"<< val <<std::endl; }
 };
 int main(int argc ,char* argv[])
 {
   B*p = new B;
   p->test();
   return 0;
 }

A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确

首先观察main函数中使用B类创建了指针p;

使用p去调用test,test在父类中,所以test中的this指针是指向A类

在test中又调用了func函数

因为func在A类中被定义为虚函数,并且在B类中重写,在加上虚函数为接口继承,

虚函数只重写函数体内容,而接口还是父类的接口

所以答案为:B->1

以上就是本篇要分享的关于多态的概念和简单实用,本人水平有限,尽管不遗余力但本篇的内容仍有不足,还请读者指正,感谢您的阅读。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】泛型编程 ② ( 函数模板与普通函数区别 )

文章目录 一、函数模板与普通函数区别1、函数模板与普通函数区别2、代码示例 - 函数模板与普通函数区别 一、函数模板与普通函数区别 1、函数模板与普通函数区别 函数模板与普通函数区别 : 主要区别在于它们能够处理的 数据类型数量 和 灵活性 ; 自动类型转换 : 函数模板 不允许…

程序员进阶之路,该怎么走?

时代洪流&#xff0c;大浪淘沙。 逆水行舟&#xff0c;不进则退。 如果你游的速度慢于水流&#xff0c;要么你就是被剩下的沙子&#xff0c;要么就是即将被打翻的行舟了。。。 身为程序员时刻保持危机感&#xff0c;然后陷入内卷...... 卷又卷不赢&#xff0c;躺又躺不平。 …

基于stm32f103系列的简单软件I2C和硬件I2C通讯

这篇文章主要分为三个部分来阐述&#xff0c;分别是I2C的基本知识&#xff0c;软件I2C通讯&#xff0c;硬件I2C通讯。I2C的基本知识这一块&#xff0c;部分讲解以及图表来自b站江科大的up&#xff0c;很感谢这位up&#xff0c;大家可以关注一波。操作实现的时候&#xff0c;up使…

2022年06月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 广场中有声控喷泉,当声音的音量大于60的时候,喷泉就会喷出水,现在的音量为30,下列哪个选项可以让喷泉喷出水? A: B: C: D: 答案:B 当前声音的音量为30,需要将声音增加到60以上就可以让喷泉喷出水,选项A将声音…

cadence virtuoso layout drc error

问题&#xff1a; The BORDER layer must enclose all chip layout patterns, which all chip layout patterns include seal ring if seal ring has been added by designers. This rule checking includes the layers of DNW,AA,NW,NC,PC,MVN, MVP,DG,GT,SN,SP,SAB,CT,M1,V1…

Java 轻松删除PDF指定页、空白页 (免费工具分享)

对PDF页面的增删通常需要借助专门的工具&#xff0c;而这些工具一般需要付费才能使用。那么我们可以通过Java代码免费实现这一功能吗&#xff1f;答案是肯定的。这篇文章就教大家如何使用一个免费的国产Java库来删除PDF中的指定页面或者删除PDF中的空白页。 使用Java快速删除PD…

2022年03月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 天天收到了一个语音机器人,当天天说“a”的时候,机器人会说“apple”,当天天说“b”的时候,机器人会说“banana”, 当天天说“c”的时候,机器人会说“cat”,如果天天说其它内容,机器人就会说“I don’t know”。机器人可…

【论文精读】VOYAGER: An Open-Ended Embodied Agent with Large Language Models

Understanding LSTM Networks 前言Abstract1 Introduction2 Method2.1 Automatic Curriculum2.2 Skill Library2.3 Iterative Prompting Mechanism 3 Experiments3.1 Experimental Setup3.2 Baselines3.3 Evaluation Results3.4 Ablation Studies3.5 Multimodal Feedback from …

Vue3实现 SKU 规格

效果图 1 HTML 基本结构 1.1 遍历 SKU 规格数据 <template><div class"productConten"><div v-for"(productItem, productIndex) in specifications" :key"productItem.name"><div class"productTitle">{…

OpenCV的应用——道路边缘检测

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;它提供了丰富的图像处理和计算机视觉算法&#xff0c;使得开发者可以便捷地进行图像处理、对象识别、图像分割等任务。道路边缘检测是计算机视觉中的重要应用之一&…

Hive入门--学习笔记

1&#xff0c;Apache Hive概述 定义&#xff1a; Hive是由Facebook开源用于解决海量结构化日志的数据统计&#xff0c;它是基于大数据生态圈Hadoop的一个数据仓库工具。 作用&#xff1a; Hive可以用于将结构化的数据文件【映射】为一张表&#xff0c;并提供类SQL查询功能。 H…

前端实现RSA非对称加密及生成RSA公私密钥

前端实现RSA非对称加密 RSA简介安装jsencryptRSA加密RSA解密如何生成公私秘钥&#xff08;windows&#xff09; RSA简介 RSA用于保密性时&#xff0c;就是公钥加密&#xff0c;私钥解密。 因为公钥是可以公开了&#xff0c; 那么任何人都可以使用公钥对信息进行加密&#xff0…

嵌入式Linux开发,NFS文件系统挂载

在嵌入式linix的开发中&#xff0c;经常会需要在pc端和板端互相传输文件&#xff0c;优先可选择ftp传输&#xff0c;但是有些嵌入式板端不支持&#xff0c;只能使用nfs这种方式&#xff0c;即pc端作为服务端&#xff0c;板端作为客户端&#xff0c;将pc端的某个文件夹挂载到板端…

时间序列预测各类算法探究上篇

前言&#xff1a; 最近项目需要对公司未来业绩进行预测&#xff0c;以便优化决策&#xff0c;so 研究一下时序算法。纯个人理解&#xff0c;记录以便备用&#xff08;只探究一下原理&#xff0c;所有算法都使用基本状态&#xff0c;并未进行特征及参数优化&#xff09;。 环境…

Windows本地配置带GPU的Pytorch环境

首先需要安装并配置好Anaconda环境&#xff0c;安装教程教程随便找一个就好。 第一步&#xff1a;安装好之后创建conda虚拟环境&#xff1a; conda create -n your_env_name pythonx.x 第二步&#xff1a;安装需要版本的pytorch&#xff1a;pytorch下载链接 cu100/torch-1.2…

很多工程师,最后都是被生活裹挟,没法一直在技术路径走到极致

最近比较少更了&#xff0c;但内容一直在写&#xff0c;只是从长文变成了短文&#xff0c;直接发朋友圈了。 如果喜欢我写的内容&#xff0c;请移步到朋友圈。 我是一个不喜欢讲哲理的人&#xff0c;感觉哲学都是理论&#xff0c;都是鸡血&#xff0c;很难落地&#xff0c;我…

Android开发中遇到的问题请求帮助分析解决

本篇文章主要寻求广大的网友&#xff0c;对我遇到的问题进行分析解答&#xff0c;希望能给出更好的&#xff0c;更优化的方法。话不多说先上遇到的问题的流程图的分析&#xff1a; 以上就是流程分析图&#xff0c;希望能够尽快解决&#xff0c;希望得到大家的支持。再次本人非常…

(Matalb回归预测)GWO-BP灰狼算法优化BP神经网络的多维回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码&#xff1a; 四、完整程序数据使用说明下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Mata…

比特币上的人工智能

以感知机为例 人工智能&#xff0c;尤其是机器学习形式的人工智能&#xff0c;最近取得了巨大的进步&#xff0c;应用范围从人脸识别到自动驾驶汽车。我们建议将 AI 与比特币区块链结合起来&#xff0c;以获得许多其他方式无法实现的显着优势&#xff1a; 公开透明&#xff1a…

腾讯云新用户优惠券如何领取?详细教程来了!

腾讯云一直致力于为广大用户提供优质、高效的云计算服务。为了吸引新用户&#xff0c;腾讯云推出了新用户专属优惠券&#xff0c;本文将详细介绍如何领取腾讯云新用户优惠券&#xff0c;助力大家轻松上云&#xff01; 一、腾讯云新用户优惠券领取 领券入口&#xff1a;https:/…