多态——C++第三大特性

news2025/1/31 8:00:34

目录

一、多态的概念

1、概念

二、多态的定义及实现

1、构成条件

2、虚函数

3、虚函数的重写

4、C++11提供了override和final两个关键字,可以帮助用户检测是否重写

5、重载、覆盖(重写)、隐藏(重定义)的对比

 三、抽象类

1、概念

2、接口继承和实现继承

四、多态的原理

1、虚函数表

2、多态的原理


一、多态的概念

1、概念

当不同的对象去完成时会产生出不同的状态。

举个栗子:比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人
买票时是优先买票。
再举个栗子: 最近为了争夺在线支付市场,支付宝年底经常会做诱人的扫红包-支付-给奖励金的
活动。那么大家想想为什么有人扫的红包又大又新鲜8块、10块...,而有人扫的红包都是1毛,5
毛....。其实这背后也是一个多态行为。支付宝首先会分析你的账户数据,比如你是新用户、比如
你没有经常支付宝支付等等,那么你需要被鼓励使用支付宝,那么就你扫码金额 =
random()%99;比如你经常使用支付宝支付或者支付宝账户中常年没钱,那么就不需要太鼓励你
去使用支付宝,那么就你扫码金额 = random()%1;总结一下:同样是扫码动作,不同的用户扫
得到的不一样的红包,这也是一种多态行为。ps:支付宝红包问题纯属瞎编,大家仅供娱乐。


二、多态的定义及实现

1、构成条件

必须通过基类的指针或者引用调用虚函数

被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

2、虚函数

被virtual修饰的类成员函数称为虚函数

public:
	virtual void BuyTicket()
	{
		cout << "买票-全价" << endl;
	}

3、虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数

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;
}

两个例外:

1、协变(基类与派生类虚函数返回值类型不同

派生类重写基类虚函数时,与基类虚函数返回值类型不同。即基类虚函数返回基类对象的指
针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变。
 

class A
{

};
class B :public A
{

};
class Person
{
public:
	virtual A* f()
	{
		return new A;
	}
};
class Student :public Person
{
public:
	virtual B* f()
	{
		return new B;
	}
};

2、析构函数的重写(基类与派生类析构函数的名字不同

如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,
都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。虽然函数名不相同,
看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处
理,编译后析构函数的名称统一处理成destructor。

class Person
{
public:
	virtual ~Person()
	{
		cout << "~Person()" << endl;
	}
};
class Student :public Person
{
public:
	virtual ~Student()
	{
		cout << "~Student()" << endl;
	}
};
//delete对象调用析构函数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数
int main()
{
	Person* p1 = new Person;
	Person* p2 = new Student;
	delete p1;
	delete p2;
	return 0;
}

4、C++11提供了override和final两个关键字,可以帮助用户检测是否重写

1、final:修饰虚函数,表示该虚函数不能再被重写

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

class Car
{
public:
	virtual void Drive()
	{

	}
};
class Benz :public Car
{
public:
	virtual void Drive()override
	{
		cout << "奔驰舒服" << endl;
	}
};

5、重载、覆盖(重写)、隐藏(重定义)的对比

 三、抽象类

1、概念

纯虚函数:在虚函数的后面写上=0

抽象类:包含纯虚函数的类

抽象类不能实例化出对象

派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。

class Car
{
public:
	virtual void Drive() = 0;
};
class Benz :public Car
{
public:
	virtual void Drive()
	{
		cout << "奔驰舒服" << endl;
	}
};
class BMW :public Car
{
public:
	virtual void Drive()
	{
		cout << "BMW好操控" << endl;
	}
};
void Test()
{
	Car* pBenz = new Benz;
	pBenz->Drive();
	Car* pBMW = new BMW;
	pBMW->Drive();
}

2、接口继承和实现继承

普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实
现。

虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成
多态,继承的是接口。所以如果不实现多态,不要把函数定义成虚函数。


四、多态的原理

1、虚函数表

一个含有虚函数的类中都至少有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也叫虚表。

class Base
{
public:
	virtual void Func1()
	{
		cout << "Base::Func1()" << endl;
	}
	virtual void Func2()
	{
		cout << "Base::Func2()" << endl;
	}
	void Func3()
	{
		cout << "Base::Func3()" << endl;
	}
private:
	int _b = 1;
};
class Derive :public Base
{
public:
	virtual void Func1()
	{
		cout << "Derive::Func1()" << endl;
	}
private:
	int _d = 2;
};
int main()
{
	Base b;
	Derive d;
	return 0;
}

测试以上代码,我们知道——

Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖。重写是语法的叫法,覆盖是原理层的叫法。

虚函数表本质上是一个存虚函数指针的指针数组。

2、多态的原理

(250条消息) c++ 多态原理详解_不倒翁*的博客-CSDN博客_c++多态原理icon-default.png?t=M85Bhttps://blog.csdn.net/qq_51579696/article/details/124556099?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167102282216782425155307%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=167102282216782425155307&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~hot_rank-4-124556099-null-null.142^v68^control,201^v4^add_ask,213^v2^t3_control1&utm_term=%E5%A4%9A%E6%80%81%E7%9A%84%E5%8E%9F%E7%90%86&spm=1018.2226.3001.4187

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

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

相关文章

pytorch环境配置

pytorch环境配置pytorch环境配置1.NVIDIA驱动安装与更新1.查看自己的电脑显卡版本2.下载显卡驱动3.安装与验证2.pytorch环境安装1.打开anaconda的终端2. 创建虚拟环境3.换源4.安装5.验证3.pycharm项目的pytorch环境设置pytorch环境配置 使用Anacondapycharm搭建pytorch环境 提…

常见的四大搜索引擎区别

一般应用或网站的信息会存储在数据库中&#xff0c;而随着时间的推移&#xff0c;数据库中的信息量达到一个量级后会出现访问速度变慢的情况&#xff0c;例如用户在客户端搜索一个商品名称&#xff0c;系统可能加载了好几秒才显示数据&#xff0c;这个时候就需要进行一些优化处…

ET框架(三)

Model》数据 HotFix》行为 ET框架中的ECS和Unity的ECS无关 hotfix 静态类静态方法>行为 可以控制组件 Model》数据 继承Entity IAwake初始化 Scene实体的子实体类型 特殊&#xff1a; Unity.hotfixView : Unity相关的行为 Unity .modeView: Unity相关的数据 代码公用&a…

WSL_01 Windows WSL 安装并配置镜像与SSH

文章目录1 WSL介绍2 安装步骤2.1 启用适用于 Linux 的 Windows 子系统2.2 检查运行 WSL 2 的要求2.3 启用虚拟机功能2.4 下载 Linux 内核更新包2.5 将 WSL 2 设置为默认版本2.6 安装所选的Linux 分发解决无法打开微软商店2.6.1 配置网络2.6.2 使用官方教程的链接2.6.3 使用命令…

Redis实战——达人探店

目录 1、发布笔记 1.1 上传图片 1.2. 发表博文功能&#xff1a; 2. 查看探店笔记 3. 点赞功能的实现 4. 点赞排行榜的实现 1、发布笔记 笔记类似点评网站的评价&#xff0c;往往是图文结合。 对应的表有两个 tb_blog&#xff1a;探店笔记表&#xff0c;包含笔记中的…

java计算机毕业设计springboot+vue高校本科学生综评系统

项目介绍 通篇文章的撰写基础是实际的应用需要,然后在架构系统之前全面复习大学所修习的相关知识以及网络提供的技术应用教程,以远程教育系统的实际应用需要出发,架构系统来改善现高校本科学生综评系统工作流程繁琐等问题。不仅如此以操作者的角度来说,该系统的架构能够对多媒…

网络流量回溯分析助力企业实现高效率运维(二)

背景 汽车配件电子图册系统是某汽车集团的重要业务系统。业务部门反映&#xff0c;汽车配件电子图册调用图纸时&#xff0c;出现访问慢现象。 某汽车总部已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和历史原始流量。本次分析重点针对汽车配件电子图册系…

在Python里使用ChatGPT

前言 近来chatGPT挺火的&#xff0c;也试玩了一下&#xff0c;确实挺有意思。这里记录一下在Python中如何去使用chatGPT。 本篇文章的实现100%基于 chatGPT&#xff0c;我是搬运工无疑了&#xff01;&#xff01;&#xff01; 本片文章比较简单&#xff0c;下一篇基于本文章来写…

景联文科技:推动智慧医疗进程,浅谈运用到的数据标注技术

“近年来&#xff0c;人工智能蓬勃发展&#xff0c;不断赋能医疗健康领域&#xff0c;改善患者的就医体验&#xff0c;有效提高医疗质量。智能医疗的实现需要许多专业且精准的标注数据不断对智慧医疗技术中包含的算法模型进行训练调优。” 从2015年至今&#xff0c;我国急性脑梗…

java+MySQL 002ssm病人健康档案管理系统#毕业设计

随着时代的发展,人们对健康越来越重视。如何呢能够更好的对病人的健康档案信息进行管理是当前很多人关心的一个问题。本期系统也是出于这样的目的而进行开发的。 研究内容 1.不同用户的登录问题&#xff1a;根据用户的类别;超级管理员、普通用户;实现用户操作权限的区分并显示不…

三、数据链路层(四)流量控制和可靠传输机制

目录 4.1流量控制和可靠传输机制 4.2三种传统ARQ方式 4.2.1单帧滑动窗口与停止-等待协议 4.2.2多帧滑动窗口与后退N帧协议&#xff08;GBN&#xff09; 4.2.3多帧滑动窗口与选择重传协议&#xff08;SR&#xff09; 4.2.4三种ARQ协议窗口大小问题 4.2.5信道利用率、信道…

视频号怎么做呢?如何发视频号?

视频号怎么做呢&#xff1f;如何发视频号&#xff1f; 视频号怎么做呢&#xff1f;如何发视频号&#xff1f; 1、明确方向 首先明确自己要做什么类型的账号&#xff0c;下面是常见的一些账号属性&#xff1a; 商品带货号美食号知识号影视号游戏号书单号音乐号家庭生活号医疗号…

JAVA开发(Redis中key的设计)

在使用redis存储数据中&#xff0c;我们可以使用任何限定长度的字符串。但是还是需要注意点规范。一般是使用树形结构 一、redis中key的设计 我总结一下几种&#xff1a; 1、使用系统结构命名法 会员系统&#xff1a; 如&#xff1a;member:service:save:user member:servi…

[附源码]Node.js计算机毕业设计高校党建信息平台Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

2022年电商年,电商企业怎么从抖音直播带货的包围网中脱颖而出

对于电商企业来说&#xff0c;2022年是非常重要的一年。多元的内容创作、多平台的发展、建立内容矩阵等方面都在时刻考验着电商企业的决策智慧&#xff0c;如何获得确定性的增长和追求长期价值&#xff0c;才是电商企业们做出正确选择的关键所在。 11月23日&#xff0c; 2022抖…

基于jsp+mysql+ssm多用户新闻发布管理系统-计算机毕业设计

项目介绍 新闻发布系统又叫做内容管理系统&#xff0c;是一个基于新闻和内容管理的全站管理系统。新闻发布系统是基于B/S模式开发的系统&#xff0c;该系统可以将杂乱无章的信息&#xff08;包括文字、图片和影片&#xff09;经过预先组织编排&#xff0c;合理有序地呈现在大家…

MapReduce词频统计演练进阶

目录 创建词频统计映射器类 创建词频统计驱动器类 第一次测试运行 修改词频统计映射器类WordCoutMapper类 修改词频统计驱动器WordCountDriver类 第二次测试运行 创建词频统计归并器类 第三测试运行 修改词频统计归并器类 第四次测试运行 修改词频统计驱动器类&#…

模拟实现字符串相关函数

上篇的延续 assert #include <stdio.h> #include <string.h> #include <assert.h> void my_strcpy(char* dest, char* src) {assert(src!NULL);//断言 满足某个条件 不允许发生什么事情的时候用断言assert(dest!NULL);while (*dest *src)//非0为真 0为假…

一文搞懂Vue2源码实现原理~ 手写Vue2系列~

Iterator&#xff08;遍历器&#xff09;的概念 JavaScript 原有的表示“集合”的数据结构&#xff0c;主要是数组&#xff08;Array&#xff09;和对象&#xff08;Object&#xff09;&#xff0c;ES6 又添加了Map和Set。这样就有了四种数据集合&#xff0c;用户还可以组合使…

KEIL调试正在运行的程序

问题现象 有时程序跑着跑着就飞了&#xff0c;但此时却没有接仿真器&#xff0c;不能停下来看运行状态。如果重新启动调试&#xff0c;会破坏现场。有没有办法attach到应用程序上调试呢&#xff1f; 答案是肯定的。 解决措施 在调试选项中&#xff0c;取消以下选择项 Option…