关于多态~

多态的基本概念

多态是c++面向对象的三大特性之一

多态分为两类:静态多态和动态多态

静态多态:函数重载,运算符重载,复用函数名

动态多态:派生类和虚函数实现运行时多态

静态多态和动态多态的区别:

静态多态函数地址早绑定------在编译阶段确定函数地址

动态多态函数地址晚绑定------在运行阶段确定函数地址

//多态基本概念
class Animal {
public:
	//virtual关键字把函数变为虚函数 目的是让函数地址晚绑定,在运行时才确定
	virtual void speken() {
		cout << "动物在说话" << endl;
	}
};
//函数重写:返回值类型、函数名、参数都一致
//函数重写和重载不一样,重载不用返回值类型来区分
class Cat :public Animal {
public:
	//重写父类成员函数
	void speken() {
		cout << "小猫在说话" << endl;
	}
};
class Dog :public Animal {
public:
	//重写父类成员函数
	void speken() {
		cout << "小狗在说话" << endl;
	}
};
//父类可以引用子类
//父类的引用,使子类可以任意变换,虚函数提供运行时确定
//如果不是虚函数,则函数在定义时,如donwu.speken();已经确定了其指向(父类)
void DoSpeak(Animal& donwu) {
	donwu.speken();
}
//多态使用条件:父类指针或引用指向子类对象
void test01() {
	Cat coke;
	DoSpeak(coke);
	Dog gg;
	DoSpeak(gg);
}
int main()
{
	test01();
}

下面通过案例讲解

多态案例1---计算机器

//多态案例:计算器实现
//普通写法
class Calculator {
public:
	int getResult(string oper) {
		if (oper == "+") {
			return m_Num1 + m_Num2;
		}
		else if (oper == "-") {
			return m_Num1 - m_Num2;
		}
		else if (oper == "*") {
			return m_Num1 * m_Num2;
		}
	}
	int m_Num1;
	int m_Num2;
};
void test01() {
	Calculator count;
	count.m_Num1 = 10;
	count.m_Num2 = 10;
	cout << count.m_Num1 << "+" << count.m_Num2 << "=" << count.getResult("+") << endl;
	cout << count.m_Num1 << "-" << count.m_Num2 << "=" << count.getResult("-") << endl;
	cout << count.m_Num1 << "*" << count.m_Num2 << "=" << count.getResult("*") << endl;
}
//多态方法(提倡)
//先提供一个抽象类
class AbstractCalculator {
public:
	virtual int getResult() {
		return 0;
	}
	int m_Num1;
	int m_Num2;
};
//创建加法计算器
class Addcalculator:public AbstractCalculator {
public:
	int getResult() {
		return m_Num1 + m_Num2;
	}
};
//创建减法计算器
class SubCalculator :public AbstractCalculator {
public:
	int getResult() {
		return m_Num1 - m_Num2;
	}
};
//创建乘法计算器
class MulCalculator :public AbstractCalculator {
public:
	int getResult() {
		return m_Num1 * m_Num2;
	}
};
void test02() {
	//父类的指针或引用指向子类对象
	AbstractCalculator* abc = new Addcalculator;
	abc->m_Num1 = 100;
	abc->m_Num2 = 100;

	cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;
	//用完记得销毁数据
	delete abc;

	abc = new SubCalculator;
	abc->m_Num1 = 100;
	abc->m_Num2 = 100;

	cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;
	delete abc;

	abc = new MulCalculator;
	abc->m_Num1 = 100;
	abc->m_Num2 = 100;

	cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getResult() << endl;
	delete abc;
}
int main()
{
	//开闭原则:打开扩展 关闭修改
	//test01();
	test02();
}

纯虚函数和抽象类

//类中只要有一个纯虚函数就称作抽象类
//抽象类无法实例化对象
//子类继承后必须重写父类的纯虚函数,不然也属于抽象类 

class Base {
public:
	virtual void func() = 0;//纯虚函数
};
class Son :public Base {
public:
	virtual void func() {
		cout << "子类重写纯虚函数" << endl;
	}
};
void test01() {
	//Base base;抽象类无法实例化对象
	//new Base;栈区堆区中都不行
	Son s;
	s.func();
}
int main()
{
	test01();
}

下面再通过一个案例巩固 

 多态案例2---制作饮品

//多态案例:制作饮品
class AbstractDrinking {
public:
	//煮水
	virtual void Boil() = 0;
	//冲泡
	virtual void Brew() = 0;
	//倒入杯中
	virtual void PourInCup() = 0;
	//加入辅料
	virtual void PutSomething() = 0;
	//制作饮品
	void makeDrink() {
		Boil();
		Brew();
		PourInCup();
		PutSomething();
	}
};
//制作咖啡
class Coffee :public AbstractDrinking {
public:
	//煮水
	virtual void Boil() {
		cout << "煮泉水" << endl;
	}
	//冲泡
	virtual void Brew() {
		cout << "冲泡咖啡" << endl;
	}
	//倒入杯中
	virtual void PourInCup() {
		cout << "倒入杯中" << endl;
	}
	//加入辅料
	virtual void PutSomething() {
		cout << "加入糖和牛奶" << endl;
	}
};
//制作茶水
class Tea :public AbstractDrinking {
public:
	//煮水
	virtual void Boil() {
		cout << "煮泉水" << endl;
	}
	//冲泡
	virtual void Brew() {
		cout << "冲泡茶叶" << endl;
	}
	//倒入杯中
	virtual void PourInCup() {
		cout << "倒入杯中" << endl;
	}
	//加入辅料
	virtual void PutSomething() {
		cout << "加入菊花" << endl;
	}
};
void DoWork(AbstractDrinking* abs) {//父类指针或引用指向子类对象
	abs->makeDrink();
	delete abs;//堆区数据记得释放
}
void test01()
{
	DoWork(new Coffee);
	cout << "----------" << endl;
	DoWork(new Tea);
}
int main()
{
	test01();
}

虚析构和纯虚析构

//虚析构和纯虚析构
class Animal {
public:
	Animal() {
		cout << "Animal构造函数调用" << endl;
	}	
	virtual void speak() {
		cout << "动物在叫" << endl;
	}
	//当你有一个指向派生类对象的基类指针,(纯)虚析构函数确保了这个对象被删除时调用了基类析构函数后也会调用派生类析构函数
	// 这样就解决了子类中也开辟了堆区数据的情况
	//虚析构
	/*virtual~Animal() {
		cout << "Animal析构函数调用" << endl;
	}*/
	//纯虚析构(需类内声明,类外定义)
	virtual~Animal() = 0;
};
Animal::~Animal() {
	cout << "Animal析构函数调用" << endl;
}
class Cat :public Animal {
public:
	Cat(string name) {
		m_Name = new string(name);
		cout <<"Cat构造函数调用" << endl;
	}
	virtual void speak() {
		cout << *m_Name << "小猫在叫" << endl;
	}
	~Cat() {
		if(m_Name!=NULL)
		{
			cout << "cat析构函数调用" << endl;
			delete m_Name;
			m_Name = NULL;
		}
	}
private:
	string* m_Name;
};
void test01() {
	Animal* animal = new Cat("Tom");
	animal->speak();
	delete animal;
	//父类的指针或引用指向子类对象 要让其指向子类析构函数,得将父类析构函数变为虚析构或者纯虚析构
}
int main()
{
	test01();
}

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

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

相关文章

高项第四版 十大管理及49个过程【背】作业分享

项目管理 1.十大管理【背】 包括&#xff08;口诀:范进整狗子&#xff08;沟质&#xff09; 才&#xff08;采&#xff09;干成疯子&#xff08;风资&#xff09;&#xff09;: &#xff08;1&#xff09;项目整合管理:识别、定义、组合、统一和协调各项目管理过程组的各个过…

OpenCV 入门(三)—— 车牌筛选

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

【SSM进阶学习系列丨分页篇】PageHelper 分页插件集成实践

文章目录 一、说明什么是分页PageHelper介绍 二、导入依赖三、集成Spring框架中四、编写Service五、编写Controller六、编写queryAllByPage页面展示数据 一、说明 什么是分页 ​ 针对分页&#xff0c;使用的是PageHelper分页插件&#xff0c;版本使用的是5.1.8 。 ​ 参考文档…

【typescript 小秘籍 - 类型自动推导】

今天发现个typescript的小技巧&#xff0c;原来在vscode里面 typescript是可以根据数据&#xff0c;自动推导其类型的&#xff0c;这样就不用自己去手敲定义了。比如 鼠标移动到person上&#xff0c;可以看到 其自动推导了person的类型 然后直接复制下来 直接使用即可。

新华三VRRP配置

新华三VRRP配置 配置步骤 (1).基础配置&#xff1a; CORE1&#xff1a; [CORE1]vlan 10 //创建vlan10 [CORE1-vlan10]int vlan 10 //进入vlanif 10 [CORE1-Vlan-interface10]ip add 192.168.10.1 24 //配置ip [CORE1-Vlan-interface10]int g1/0/2 //进入接口 [C…

Map集合的实现类~TreeMap

重复依据&#xff1a;通过对键进行排序 先创建Student类&#xff0c;并在主函数new对象&#xff0c;然后创建TreeMap&#xff1a; 建立红黑树&#xff0c;需要在Student类后面实现类的接口&#xff1a; 重写其中的compareTo方法&#xff1a; 或者可以自定义比较器&#xff1a; …

2024五一劳动节活动策划方案

2024五一劳动节打工人青松游园大会&#xff08;劳动节放青松主题&#xff09;活动策划方案-51P.pptx 活动策划信息&#xff1a; 方案页码&#xff1a;51页 文件格式&#xff1a;PPT 方案简介&#xff1a; 劳动是世界上最伟大的事 所以我们该把一些劳动留给明天&#xff0…

windows系统远程执行脚本部署项目操作手册

windows系统远程执行脚本部署项目操作手册 windows系统远程执行脚本部署项目 如果频繁的需要部署项目到远程的服务器上,每次要手动上传项目,然后停止项目,启动项目,很麻烦,像Linux天生支持远程执行脚本 Windows借助工具也可以做到. 安装WinSCP软件 自行下载软件或关注我的公…

荷香堪筑梦,鸳鸯和月寻。(变相BFS搜索)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 3 4 2 .... ***. ..a. 输出 yes 思路&#xff1a; 根据题意&#xff0c;这里 1 s 可以移动多次&#xff0c;我们将每次可以移动避开雪的的位置存储起来&#xff0c;判断当…

强大的禄得可转债自定义因子轮动系统完成,可转债三低为例子

经过几天的测试终于完成了可转债自定义因子轮动&#xff0c;超过1000行的源代码 我提供了服务器的数据支持自动api下载&#xff0c;我给大家维护数据 网页 http://120.78.132.143:8023/ 录得数据支持http://120.78.132.143:8023/lude_data_app api数据支持&#xff0c;我提供…

每天五分钟计算机视觉:通过交并比判断对象检测算法的性能

本文重点 在对象检测领域,交并比(Intersection over Union,简称IoU)是衡量算法性能的重要指标之一。它不仅直观地反映了预测框与真实框之间的重叠程度,还是判断算法是否“运行良好”的关键依据。 那个定位是好的? 对象检测任务中,我们希望不仅检测到对象,同时我们还希…

嵌入式开发常见概念简介

目录 0. 《STM32单片机自学教程》专栏总纲 API Handle(句柄) 0. 《STM32单片机自学教程》专栏总纲 本文作为专栏《STM32单片机自学教程》专栏其中的一部分&#xff0c;返回专栏总纲&#xff0c;阅读所有文章,点击Link: STM32单片机自学教程-[目录总纲]_stm32 学习-CSD…

excel如何将多列数据转换为一列?

这个数据整理借用数据透视表也可以做到&#xff1a; 1.先将数据源的表头补齐&#xff0c;“姓名” 2.点击插入选项卡&#xff0c;数据透视表&#xff0c;在弹出对话框中&#xff0c;数据透视位置选择 现有工作表&#xff0c;&#xff08;实际使用时新建也没有问题&#xff09;…

【C/C++】设计模式——单例模式

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

vue快速入门(五十)重定向

注释很详细&#xff0c;直接上代码 上一篇 本篇建立在之前篇目前提下针对重定向进行演示 新增内容 路由重定向写法 源码 src/router/index.js //导入所需模块 import Vue from "vue"; import VueRouter from "vue-router"; import myMusic from "/v…

基于springboot实现校园失物招领系统【项目源码+论文说明】

基于springboot实现校园失物招领系统演示 摘要 身处网络时代&#xff0c;随着网络系统体系发展的不断成熟和完善&#xff0c;人们的生活也随之发生了很大的变化&#xff0c;身边经常有同学丢失了东西或者衣服而烦恼&#xff0c;为了找到自己心爱的物品疲于奔命&#xff0c;还不…

代码随想录算法训练营第十九天:二叉树go

代码随想录算法训练营第十九天&#xff1a;二叉树go 226.翻转二叉树 力扣题目链接(opens new window) 翻转一棵二叉树。 ​​ 这道题目背后有一个让程序员心酸的故事&#xff0c;听说 Homebrew的作者Max Howell&#xff0c;就是因为没在白板上写出翻转二叉树&#xff0c;最…

Python批量计算多张遥感影像的NDVI

本文介绍基于Python中的gdal模块&#xff0c;批量基于大量多波段遥感影像文件&#xff0c;计算其每1景图像各自的NDVI数值&#xff0c;并将多景结果依次保存为栅格文件的方法。 如下图所示&#xff0c;现在有大量.tif格式的遥感影像文件&#xff0c;其中均含有红光波段与近红外…

python实验三 实现UDP协议、TCP协议进行服务器端与客户端的交互

实验三 实验题目 1、请利用生成器构造一下求阶乘的函数Factorial()&#xff0c;定义一个函数m()&#xff0c;在m()中调用生成器Factorial()生成小于100的阶乘序列存入集合s中&#xff0c;输出s。 【代码】 def factorial():n1f1while 1:​ f * n​ yield (f)​ n1…

做安卓应用开发的我,转前端开发了

距离转前端开发已经快3个月了&#xff0c;现在自己也慢慢的熟悉了开发。 在2月份的时候。领导找我们移动小组的谈话&#xff0c;主要是关于转前端或者后端的问题。由于公司移动端的选型&#xff0c;对安卓原生的需求降低&#xff0c;问下我们转其他开发的需求。 我毫不犹豫的选…