C++ 面向对象特征4 多态(Polymorphism)

news2024/9/23 15:27:09

目录

1、对多态的理解

2、实现多态的例子

3、多态的意义

4、静态联编与动态联编


1、对多态的理解

同一对象可以有多重层级递进身份

在不同的场合中,被外界所关注的是不同的身份,但本质和应有的行为并不会因外界眼光而改变。

比如说我自己 kali-Myon(一个实体)

生物学家会认为我(该实体)是人类 ;

教育局认为我是一名学生;

西南科技大学认为我是一名大学生。

但我目前在做什么呢?上大学对吧,我做着我自己最本质身份(大学生)的行为。

一个对象就是内存中的一个实体,它只能属于一个确定的类:最精确的子类

它可能在不同处被视为不同身份,但它本质行为方式与外界如何看待它是无关的。

为了保证一个对象执行其最本质身份的行为

我们可以利用虚函数重写和指向子类对象的父类指针来实现

2、实现多态的例子

eg1:

#include <iostream>
using namespace std;

class Human {  //定义了一个父类
public:
	virtual void say() {
			cout << "I'm human\n";
	}
};

class Student : public Human {  //子类1公有继承父类
public:
	virtual void say() {
		cout << "I'm a student\n";
	}
};

class CollegeStudent : public Student {  //子类2公有继承子类1(对于子类2来说,子类1就相当于它的父类)
public:
	void say() {
		cout << "I'm a college student\n";
	}
};

int main() {
	CollegeStudent a;  //a是子类2的一个实例化对象
	Human* p1 = (Human*)&a;  //父类指针,指向子类对象
	Student* p2 = (Student*)&a;  //父类指针,指向子类对象
	CollegeStudent* p3 = &a;
	p1->say();  //“->”是类成员访问运算符,可以被重载,它被定义用于为一个类赋予"指针"行为,常与指针引用运算符“*”结合使用
	p2->say();  
	p3->say(); 
}

 由运行结果可以看出:通过指针调用的是对象本质子类的方法

(即collegestudent这个类中的say()函数)

eg2:

有很多的人(human),男的(man)应该去男厕所,女的(women)该去女厕所

但是有太多对象man1,man2,women1,man3,women2...

如何用func()函数让他们都能去到正确的厕所

我们只需定义一个上厕所的函数toilet()

男的还是女的都是人,都具有上厕所这个行为

human可能指向两种不同的实际对象

事实上func()并不关心实际是什么,反正都当成Human,能toilet就行

#include <iostream>
using namespace std;

class Human {
public:
	virtual void toilet() = 0;
};

class Man : public Human {
public:
	void toilet() {
		cout << "我去男厕所";
	}
};

class Woman : public Human {
public:
	void toilet() {
		cout << "我去女厕所";
	}
};

void func(Human * human) {
		human->toilet();
	}

int main() {
	
	Man man1;
	Woman woman2;
	func(&man1);
	cout << endl;
	func(&woman2);
}

运行结果:

 可以看到,man1去了男厕所,woman2去了女厕所

3、多态的意义

实现代码复用

通过“虚函数+指向子类对象的父类指针”,无需针对不同的子类写相同逻辑,统一视为其共同父类,利用指针操作即可,本质是虚函数将能做什么和怎么做分离,父类指定要做什么,子类来实现具体做法。

eg3:

比如我们要设计一个函数来求图形的面积,但是我们并不知道具体是什么图形

如果没有多态,我们就需要对每种图形都实现一个函数

但是有多态,我们只需要实现一个函数

并不关心图形具体是什么,只要能求面积就行(满足父类,是个图形,就能求面积)

#include <iostream>
using namespace std;

class Shape {  //定义了一个类shape
public:
	virtual float getS() = 0;  //在父类声明了一个纯虚函数
};

class Circle : public Shape {  //圆公有继承父类shape
private:
	float radius;
public:
	Circle(float radius)
	{
		this->radius = radius;
	}
	float getS() { return 3.14 * radius * radius; }  //在子类重写虚函数
};

class Rectangle : public Shape {  //矩形公有继承父类shape
private:
  float a;
  float b;
public:
  Rectangle(float a, float b) {
    this->a = a;
    this->b = b;
}
float getS() { return a * b; }  //在子类重写虚函数
};

void display(Shape* ptr) {  //此处实现了多态:通过父类指针调用子类重写的虚函数
	cout << ptr->getS() << endl;
}

int main() {
		Circle c(1.3);
		Rectangle r(1.5, 2.3);
		display(&c);
		display(&r);
		return 0;
}

运行结果:

4、静态联编与动态联编

上述利用虚函数重写+指针实现的多态特指运行时多态,与之相对的是编译时多态

静态联编=编译时多态=函数重载=overload

动态联编=运行时多态=虚函数重写=override

联编(bind):确定具体要调用多个同名函数中的哪一个

静态联编:在编译时就确定了要调用的是哪个函数(根据多个重载函数的参数列表确)

动态联编:直到运行时才知道实际调用的是哪个函数(根据指针指向对象的实际身份)

至此,我们已经介绍完了面向对象的四个特征:封装、派生、继承、多态。

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

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

相关文章

Dev C++中出现 undefined reference to XXX 错误的解决方式

出现 undefined reference to XXX 错误的现象&#xff1a; 主函数中调用在其他文件中定义的函数&#xff0c;编译报错&#xff1a;未定义的引用xxx。 原理&#xff1a;编译器在生成可执行文件的过程包括预处理、编译、汇编、链接&#xff0c;这4个过程&#xff0c;这个问题一般…

【AI】YOLOv3原理详解

1、前言 YOLOv1~3作者是约瑟夫雷德蒙(Joseph Chet Redmon),他的网站:https://pjreddie.com/ YOLOv1网站:https://pjreddie.com/darknet/yolov1/ YOLOv2网站:https://pjreddie.com/darknet/yolov2/ YOLOv3网站:https://pjreddie.com/darknet/yolo/ YOLOv4作者是Alexeyab…

KingbaseES V8R6 集群运维案例--备库timeline not contain minimum recovery point故障

​ 案例现象&#xff1a; KingbaseES V8R6集群备库启动后&#xff0c;加入集群失败&#xff0c;sys_log日志信息提示&#xff0c;如下图所示&#xff1a; 适用版本&#xff1a;kingbaseES V8R6 一、问题分析 在timeline对应的history文件中会记录每次timeline切换时所对应的lsn…

【C++起飞之路】初级——命名空间、输入输出流

C&#xff1a;命名空间、输入输出流 一、命名空间1、命名空间的定义2、命名空间中成员的使用非嵌套命名空间&#xff1a;嵌套命名空间&#xff1a; 3、命名空间 三种展开方式<1>指定命名空间访问<2> using声明a、using引入某个成员b、using展开命名空间❗注意&…

离散化(算法)

目录 一、离散化的概念二、离散化的模板三、离散化的应用题目思路分析代码实现 一、离散化的概念 离散化是一种将连续数据映射到离散值的过程。它通常用于优化某些算法&#xff0c;尤其是与区间查询相关的问题。 在离散化过程中&#xff0c;我们将一组实数转换为一组整数&#…

美团企业版背后,费控和「know-how」的双重苦战

在企业消费管理的赛道里&#xff0c;美团不能算新手&#xff0c;但客观来看&#xff0c;也并不算是熟练的玩家。对这家中国骨灰级的玩家而言&#xff0c;这不仅是一场费控报销的仗&#xff0c;更是一个从C到B的观念转型之路。 作者|思杭 编辑|皮爷 出品|产业家 美团再出招。 …

从零构建自己的脚手架

从零构建自己的脚手架 简介 什么是CLI CLI 全称是 Command Line Interface&#xff0c;是一类通过命令行交互的终端工具。日常工作中常用的脚手架有 vue-cli、create-react-app、angular-cli 等&#xff0c;都是通过简单的初始化命令&#xff0c;完成内容的快速构建。 为什…

Unity Audio -- (3)创建3D音效

本节会添加场景中小瀑布的音效。小瀑布的音效会有一个作用范围&#xff0c;也会根据角色所处的位置不同&#xff0c;产生不同的效果。 添加小瀑布的声音 1. 在Hierarchy中&#xff0c;点击右键&#xff0c;选择Audio -> Create Audio Source&#xff0c;将这个新的Audio So…

HEVC学习之去方块滤波

一、概要 视频编码为视频带来的压缩伪影呈现出的效果各有不同&#xff0c;但其原因总结起来为高频信息的失真以及基于块的编码消除了块与块之间的相似性。 为了弥补基于块的编码带来的影响&#xff0c;HEVC中引入了去方块滤波。 AVC中采取对44块的边界进行去方块滤波&#xf…

通过自定义域名 + SSL 的方式访问 Amazon MQ for RabbitMQ

引言&#xff1a; 一般为了解决应用解耦&#xff0c;异步处理&#xff0c;流量削峰等问题&#xff0c;实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性的架构&#xff1b;我们会引入消息队列中间件来完善架构设计。 对于需要消息传递协议的应用程序&#xff0c;…

CCFCSP 201409-2 画图

思路上很容易想到即使用一个标记数组对上过色的模块进行标记&#xff0c;最后遍历该数组得到被标记的模块数即可 #include<iostream>using namespace std;int mapp[105][105]; int ans0;int main(){int n;cin>>n;for(int i0;i<n;i){int x1,y1,x2,y2;cin>>…

【P15】JMeter 正则表达式提取器(Regular Expression Extractor)

文章目录 一、准备工作二、测试计划设计 一、准备工作 慕慕生鲜&#xff1a; http://111.231.103.117/#/login 进入网页后&#xff0c;登录&#xff0c;页面提供了账户和密码 搜索框输入“虾” 右键检查或按F12&#xff0c;打开调试工具&#xff0c;点击搜索 二、测试计划设…

【Java项目】SpringCloud项目注册到Nacos中心时显示的是内网IP导致不同服务器之间无法互相调用接口的解决并发

微服务项目地址—动动你发财的小手点一个stars吧 出现这个问题是之前我也就遇到过的&#xff0c;这个问题的情况就是&#xff1a; 我们知道微服务项目是可以把不同的项目部署在不同的服务器上从而减少某一台服务器的压力&#xff0c;我们只需要为每一个服务配置一个注册中心即…

计算机基础--计算机存储单位

一、介绍 计算机中表示文件大小、数据载体的存储容量或进程的数据消耗的信息单位。在计算机内部&#xff0c;信息都是釆用二进制的形式进行存储、运算、处理和传输的。信息存储单位有位、字节和字等几种。各种存储设备存储容量单位有KB、MB、GB和TB等几种。 二、基本存储单元…

【进阶知识】显示管理器,窗口管理器,桌面环境/桌面管理器,显示服务器

文章目录 一、显示管理器&#xff08;Display Manager&#xff09;1.1 什么是 Linux 中的显示管理器&#xff1f;1.2 不同的显示管理器1.3 其他控制台显示管理器图形界面显示管理器 二、窗口管理器&#xff08;Window Manager&#xff09;三、桌面环境/桌面管理器&#xff08;D…

AD9680之JESD204B接口2路、4路、8路的14bit 500MSPS/1GSPS/1.25GSPS采样率子卡的中文版本设计及调试经验资料分享

板卡概述&#xff1a; 【FMC155】 FMC155 是一款基于 VITA57.1 标准的&#xff0c;实现 2 路 14-bit、500MSPS/1GSPS/1.25GSPS 直流耦合 ADC 同步采集 FMC 子卡模 块。 该模块遵循 VITA57.1 规范&#xff0c;可直接与 FPGA 载卡配合使用&#xff0c;板 卡 ADC 器件采用 ADI 的…

MySQL基础篇补充 | 单行函数(数值函数、字符串函数、日期函数、流程控制函数、加密与解密函数、MySQL信息函数)

目录 一&#xff1a;单行函数 1. 数值函数 &#xff08;1&#xff09;基本函数 &#xff08;2&#xff09;角度与弧度互换函数 &#xff08;3&#xff09;三角函数 &#xff08;4&#xff09;指数与对数 &#xff08;5&#xff09;进制间的转换 2. 字符串函数 3. 日期和…

Nginx配置浏览器缓存,页面展示更快一步

1.简介 缓存能够存储请求的响应结果&#xff0c;可以很方便的再次访问&#xff0c;使用缓存的优点是很明显的。 加速内容的访问&#xff0c;降低响应时间减少服务器的负载 Nginx不仅仅是一个web服务器&#xff0c;它也是一个web缓存服务器。通过Nginx缓存&#xff0c;我们对…

Java引用类型(强引用,软引用,弱引用,虚引用)

从Java SE2开始&#xff0c;就提供了四种类型的引用&#xff1a;强引用、软引用、弱引用和虚引用。Java中提供这四种引用类型主要有两个目的&#xff1a;第一是可以让程序员通过代码的方式决定某些对象的生命周期&#xff1b;第二是有利于JVM进行垃圾回收。 强引用&#xff08…

【Linux环境】Linux常用命令记录汇总

Linux常用命令记录汇总 一、传输命令二、打包命令三、创建文件夹或文件命令四、切换用户五、vim相关命令六、权限更改命令 一、传输命令 命令格式&#xff1a; rz 点击回车 sz 文件名 点击回车命令解释&#xff1a; rz&#xff08;receive Zmodem缩写&#xff09;上传文件&am…