C++核心编程--多态篇

4.7、多态

4.7.1、多态的基本概念

多态是C++面向对象三大特征之一

多态分为两类

  • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态:派生类和虚函数实现运行时多态

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

  • 静态多态的函数地址早绑定 - 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定 - 运行阶段确定函数地址
  1. 动态多态满足条件
    • 有继承关系
    • 子类重写父类的虚函数
  2. 动态多态使用
    • 父类的指针或引用 指向子类对象

重写:函数返回值类型 函数名 参数列表 完全一致称为重写

class Animal {
public://虚函数virtual void  spreak() {cout << "动物在说话" << endl;	}
};class Cat :public Animal {
public:void spreak() {cout << "猫在说话" << endl;}
};class Dog : public Animal {
public:void spreak() {cout << "狗在说话" << endl;}
};//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想让猫说话,就不能提前绑定,云瑶在运行阶段绑定,及地址晚绑定 
void doSpreak(Animal &animal) {animal.spreak();
}void test01() {Cat cat;doSpreak(cat);Dog dog;doSpreak(dog);
}
4.7.2、多态案例-计算器类
  • 多态的优点:
    • 代码组织结构清晰
    • 可读性强
    • 利于前期和后期扩展以及维护
//实现计算机的抽象类
class AbstractCalculator {
public:virtual int getResult() {return 0;}int m_Num1,m_Num2;
};//减法计算机类
class SubCalculator :public AbstractCalculator {
public:int getResult() {return m_Num1 - m_Num2;}
};
//加法计算机类
class AddCalculator :public AbstractCalculator {
public:int getResult() {return m_Num1 + m_Num2;}
};void test01() {AbstractCalculator *a1 = new AddCalculator;a1->m_Num1 = 100;a1->m_Num2 = 200;cout << a1->m_Num1 << " + " << a1->m_Num2 << " = " << a1->getResult() << endl;//回收a1delete a1;a1 = new SubCalculator();a1->m_Num1 = 200;a1->m_Num2 = 100;cout << a1->m_Num1 << " - " << a1->m_Num2 << " = " << a1->getResult() << endl;//回收a1delete a1;
}

image-20230930093236142

4.7.3、纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是效用子类重写的内容

因此可以将虚函数改为纯虚函数

纯虚函数语法:virtual 返回值类型 函数名 (参数列表) = 0;

当类中有了纯虚函数,这个类也称为抽象类

抽象类特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
//纯虚函数和抽象类
class Base {
public:virtual void func() = 0;
};//1、纯虚函数无法实例对象
//void test01() {
//	Base b;
//	new Base;
//}//2、子类必须重写抽象类中的纯虚函数,否则也属于抽象类
//class Son : public Base {
//public:
//
//};
//
//void test02() {
//	Son s;
//}//3、正确写法
class Son : public Base {
public:virtual void func() {cout << "func函数被调用" << endl;};
};void test03() {Base* base = new Son;base->func();
}
4.7.4、多态案例二 - 制作饮品

案例描述:

制作饮品时大致的流程为: 煮水 - 冲泡 - 导入杯中 - 加入辅料

利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡喝茶叶

image-20230930102207998

//饮品抽象类
class MakeDreak {
public:virtual void Boil() = 0;virtual void Rush() = 0;virtual void Fall() = 0;virtual void Add() = 0;void markDrink() {Boil();Rush();Fall();Add();};
};class Coffee : public MakeDreak {virtual void Boil() {cout << "煮水" << endl;}virtual void Rush() {cout << "冲泡咖啡" << endl;}virtual void Fall() {cout << "倒入杯中" << endl;}virtual void Add() {cout << "加糖和牛奶" << endl;}
};class Tea : public MakeDreak {virtual void Boil() {cout << "煮水" << endl;}virtual void Rush() {cout << "冲泡茶叶" << endl;}virtual void Fall() {cout << "倒入杯中" << endl;}virtual void Add() {cout << "柠檬" << endl;}
};//制作函数
void doWork(MakeDreak* abs) {abs->markDrink();
}void test01() {doWork(new Coffee);cout << "-----------------" << endl;doWork(new Tea);
}
4.7.5、虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方法:将父类中的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象
  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名() = 0

类名::~类名(){}

class Animal {
public:Animal() {cout << "Animal构造函数被调用" << endl;}//利用虚析构可以解决 父类指针释放子类对象virtual ~Animal(){cout << "Animal析构函数被调用" << endl;}//纯虚函数virtual void spreak()  = 0;};class Cat : public Animal {
public:Cat(string name) {cout << "Cat构造函数调用" << endl;m_Name =  new string(name);}virtual void spreak() {cout << *m_Name<<"猫正在说话" << endl;}~Cat(){if (m_Name !=NULL){cout << "Cat析构函数调用" << endl;delete m_Name;m_Name = NULL;}}string *m_Name;
};void test01() {Animal* animal = new Cat("Tom");animal->spreak();//父类指针在析构时候,不会调用子类中析构函数,//导致子类如果有堆区属性,出现内存泄露delete animal;
}
4.7.6、多态案例三 - 电脑组装

案例描述:

电脑主要组成部件为CPU (用于计算),显卡(用于显示),内存条(用于存储)将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Inter厂商和Lenovo厂商创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口

测试时组装三台不同的电脑进行工作

//cpu类
class CPU {
public://抽象的计算机函数virtual void caculate() = 0;
};//显卡类
class Graphics {
public://抽象的显卡virtual void show() = 0;
};//内存类
class RAM {
public:virtual void save() = 0;
};class Computer {
public:Computer(CPU* cpu, Graphics* gpu, RAM* ram) {m_cpu = cpu;m_gpu = gpu;m_ram = ram;}void work() {m_cpu->caculate();m_gpu->show();m_ram->save();}//提供析构函数 释放3个电脑零件~Computer(){//释放cpuif (m_cpu!=NULL){delete m_cpu;m_cpu = NULL;}//释放显卡if (m_gpu !=NULL){delete m_gpu;m_gpu = NULL;}//释放内存条if (m_ram !=NULL){delete m_ram;m_ram = NULL;}}
private:CPU* m_cpu; //CPU的零件指针Graphics* m_gpu;RAM* m_ram;
};//Intel厂商
class IntelCPU : public CPU {
public:virtual void caculate() {cout << "Intel的CPU开始计算了" << endl;}
};
class IntelGPU : public Graphics {
public:virtual void show() {cout << "Intel的GPU开始显示了" << endl;}
};
class IntelRAM : public RAM {
public:virtual void save() {cout << "Intel的RAM开始存储了" << endl;}
};//Lenovo厂商
class LenovoCPU : public CPU {
public:virtual void caculate() {cout << "AMD的CPU开始计算了" << endl;}
};
class LenovoGPU : public Graphics {
public:virtual void show() {cout << "AMD的GPU开始显示了" << endl;}
};
class LenovoRAM : public RAM {
public:virtual void save() {cout << "AMD的RAM开始存储了" << endl;}
};void test01() {//第一台电脑零件CPU * intelCpu = new IntelCPU;Graphics * IntelGpu = new IntelGPU;RAM * IntelRam = new IntelRAM;//创建第一台电脑cout << "第一台电脑开始工作" << endl;Computer * computer1 = new Computer(intelCpu, IntelGpu, IntelRam);computer1->work();delete computer1;//第二台电脑cout << "---------------------" << endl;cout << "第二台电脑开始工作" << endl;Computer* computer2 = new Computer(new LenovoCPU, new LenovoGPU, new LenovoRAM);computer2->work();delete computer2;//第三台电脑cout << "---------------------" << endl;cout << "第三台电脑开始工作" << endl;Computer* computer3 = new Computer(new LenovoCPU, new IntelGPU, new LenovoRAM);computer3->work();delete computer3;}

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

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

相关文章

校物联网智慧安全用电平台的设计和运用-安科瑞黄安南

一.前言 安全用电历来都是学校安全工作的一个重点&#xff0c;然而每年因此发生的人身伤害以及火灾事故却在继续着&#xff0c;究其原因&#xff0c;主观上是我们的防患意识淡薄&#xff0c;客观上则是由于学生在宿舍使用违规电器、乱拉电线造成的。 现代的大学生宿舍&#x…

【生物信息学】使用谱聚类(Spectral Clustering)算法进行聚类分析

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. 生成测试数据 2. 绘制初始数据分布图 3. 循环尝试不同的参数组合并计算聚类效果 4. 输出最佳参数组合 5. 绘制最佳聚类结果图 6. 代码整合 一、实验介绍…

HashMap底层源码,数据结构

HashMap的底层结构在jdk1.7中由数组链表实现&#xff0c;在jdk1.8中由数组链表红黑树实现&#xff0c;以数组链表的结构为例。 JDK1.8之前Put方法&#xff1a; JDK1.8之后Put方法&#xff1a; HashMap基于哈希表的Map接口实现&#xff0c;是以key-value存储形式存在&#xff0c…

K8S内容分发网络之集群,nginx,负载均衡,防火墙

K8S内容分发网络之集群&#xff0c;nginx&#xff0c;负载均衡&#xff0c;防火墙 一、Kubernetes 区域可采用 Kubeadm 方式进行安装。1.所有节点&#xff0c;关闭防火墙规则&#xff0c;关闭selinux&#xff0c;关闭swap交换2.修改主机名3.所有节点修改hosts文件4.调整内核参数…

闪击笔试题

选择题 ping命令不涉及什么协议? A&#xff1a;DNS B: TCP C: ARP D: ICMP B&#xff0c;ping基于ICMP协议&#xff0c;解析路由会用到ARP和DNS a、b、c三人参加学科竞赛&#xff0c;每个学科按一二三名次给x、y、z分&#xff0c;已知a得22分&#xff0c;b和c得9分&#xf…

【图论C++】链式前向星(图(树)的存储)

/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记&#xff1a;转载需获得博主本人…

人工智能的学习算法

1956年&#xff0c;几个计算机科学家相聚在达特茅斯会议&#xff0c;提出了 “人工智能” 的概念&#xff0c;梦想着用当时刚刚出现的计算机来构造复杂的、拥有与人类智慧同样本质特性的机器。其后&#xff0c;人工智能就一直萦绕于人们的脑海之中&#xff0c;并在科研实验室中…

数组和切⽚ - Go语言从入门到实战

数组和切⽚ - Go语言从入门到实战 数组的声明 package main import "fmt" func main() { var a [3]int //声明并初始化为默认零值 a[0] 1 fmt.Println("a:", a) // 输出: a: [1 0 0] b : [3]int{1, 2, 3} //声明同时初始化 fmt.Println("b:…

Airtool for Mac——高效便捷的系统菜单栏网络工具!

在我们的数字化生活中&#xff0c;对于网络连接的稳定性和速度有着越来越高的需求。为了满足您对网络质量的实时监测和分析的需求&#xff0c;我们向大家介绍一款强大的Mac系统菜单栏网络工具——Airtool&#xff01; Airtool是一款专为Mac设计的网络工具&#xff0c;它能够提…

番外5:下载+安装+配置Linux

任务前期工作&#xff1a; 01. 电脑已安装好VMware Workstation软件&#xff1b; 02.提前下载好Rhel-8.iso映像文件&#xff08;文件较大一般在9.4GB&#xff0c;建议采用迅雷下载&#xff09;&#xff0c;本人使用的以下版本&#xff08;地址ed2k://|file|rhel-8.4-x86_64-dvd…

基于PHP+MySQL的养老院管理系统

摘要 随着21世纪互联网时代的兴起&#xff0c;我们见证了人们生活方式的巨大改变。这个时代不仅深刻影响了我们的生活&#xff0c;还改变了我们对信息科学的看法。社会的各个领域都在不断发展&#xff0c;人们的思维也在不断进步&#xff0c;与此同时&#xff0c;信息的需求也与…

【React】React组件生命周期以及触发顺序(部分与vue做比较)

最近在学习React&#xff0c;发现其中的生命周期跟Vue有一些共同点&#xff0c;但也有比较明显的区别&#xff0c;并且执行顺序也值得讨论一下&#xff0c;于是总结了一些资料在这里&#xff0c;作为学习记录。 v17.0.1后生命周期图片 初始化阶段 由ReactDOM.render()触发 —…

百度交易中台之内容分润结算系统架构浅析

作者 | 交易中台团队 导读 随着公司内容生态的蓬勃发展&#xff0c;内容产出方和流量提供方最关注的“收益结算”的工作&#xff0c;也就成为重中之重。本文基于内容分润结算业务为入口&#xff0c;介绍了实现过程中的重难点&#xff0c;比如千万级和百万级数据量下的技术选型和…

用Java打印长方形、平行四边形 、三角形、菱形、空心菱形

今天复习使用嵌套for来完成一些任务&#xff0c;于是想着打印一些图形来练习 思考感悟 长方形 行数 和 每行的星星数嵌套遍历即可 平行四边形 核心&#xff1a;每行空格数总行数-行数 行数空格数132231 三角形 核心&#xff1a;每行星星数2*当前行数-1 行数星星数1123…

【VIM】VIm-plug插件

如何查找需要的插件 https://github.com/mhinz/vim-startify https://github.com/vim-airline/vim-airline https://github.com/Yggdroot/indentLine github.com/w0ng/vim-hybrid github.com/altercationi/vim-colors-solarized guithub.com/morhetz/gruvbox github.com/sc…

【2023保研】双非上岸东南网安

个人情况 学校&#xff1a;henu 专业&#xff1a;信息安全 排名&#xff1a;1/66 英语&#xff1a;六级500 竞赛&#xff1a;蓝桥杯PB国一&#xff0c;ISCC国一&#xff0c;密码数学挑战赛国三&#xff0c;还有其他一些省级水奖 论文&#xff1a;一篇EI在投&#xff08;三作通…

C++:红黑树

目录 一、关于红黑树 1、红黑树和AVL树区别 2、红黑树规则 二、红黑树 1、红黑树变色举例 2、红黑树具体情况分析 ①、情况一&#xff1a;只变色 ②、情况二&#xff1a;单旋 变色 ③、情况三&#xff1a;双旋 变色 三、红黑树的模拟实现 一、关于红黑树 1、红黑树…

王道考研计算机网络——传输层

一、传输层概述 复用&#xff1a;发送方不同的应用进程都可以使用同一个传输层的协议来传送数据 分用&#xff1a;接收方的传输层在去除报文段的首部之后能把数据交给正确的应用进程 熟知端口号就是知名端口号0-1023 客户端使用的端口号是动态变化的&#xff0c;不是唯一确定…

某房产网站登录RSA加密分析

文章目录 1. 写在前面2. 抓包分析3. 扣加密代码4. 还原加密 1. 写在前面 今天是国庆节&#xff0c;首先祝福看到这篇文章的每一个人节日快乐&#xff01;假期会老的这些天一直在忙事情跟日常带娃&#xff0c;抽不出一点时间来写东西。夜深了、娃也睡了。最近湖南开始降温了&…

Unity Urp无线延申的网格效果

无线延申的网格 该项目必须是再Urp项目 shader代码实现 Shader "Unlit/infTutorial1" {Properties{_Alpha ("Alpha", Range(0, 0.5)) 0.5}SubShader{Tags{"RenderPipeline""UniversalRenderPipeline""RenderType""…