当前位置: 首页 > news >正文

多态(个人学习笔记黑马学习)

多态分为两类

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

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

  • 静态多态的函数地址早绑定 · 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定 · 运行阶段确定函数地址

1、基本语法

#include <iostream>
using namespace std;
#include <string>//动物类
class Animal {
public://虚函数virtual void speak() {cout << "动物在说话" << endl;}
};//猫类 
class Cat :public Animal {
public://重写 函数返回值类型 函数名 参数列表 完全相同void speak() {cout << "小猫在说话" << endl;}
};//狗类
class Dog :public Animal {
public:void speak() {cout << "小狗在说话" << endl;}
};//执行说话的函数
//地址早绑定 在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定//动态多态满足条件
//1、有继承关系
//2、子类重写父类的虚函数//动态多态的使用
//父类的指针或者引用 指向子类对象void doSpeak(Animal& animal) {  //Animal& animal = cat;animal.speak();
}void test01() {Cat cat;doSpeak(cat);Dog dog;doSpeak(dog);
}int main() {test01();system("pause");return 0;
}

2、案例1:计算器类

案例描述:
分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类

#include <iostream>
using namespace std;
#include <string>//普通写法
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;//操作数1int m_Num2;//操作数2
};void test01() {//创建计算器对象Calculator c;c.m_Num1 = 10;c.m_Num2 = 10; cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.getResult("+") << endl;cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.getResult("-") << endl;cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.getResult("*") << endl;
}//利用多态实现计算器
//多态好处:
// 1、组织结构清晰
// 2、可读性强
// 3、对前期和后期拓展和维护性高
//实现计算器抽象类
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 = NULL;		//减法运算abc = new SubCalculator;abc->m_Num1 = 100;abc->m_Num2 = 100;cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;delete abc;abc = NULL;//乘法运算abc = new MulCalculator;abc->m_Num1 = 100;abc->m_Num2 = 100;cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getResult() << endl;delete abc;abc = NULL;}int main() {//test01();test02();system("pause");return 0;
}


3、纯虚函数和抽象类

#include <iostream>
using namespace std;
#include <string>class Base {
public://纯虚函数//只要有一个纯虚函数,这个类称为抽象类//抽象类特点://1、无法实例化对象//2、抽象类的子类 必须要重写父类中的纯虚函数,否则也属于抽象类virtual void func() = 0;
};class Son :public Base {
public:virtual void func() {cout << "fun()函数调用" << endl;}
};void test01() {//Base b;//抽象类无法实例化对象//new Base;//抽象类无法实例化对象//Son s;//子类必须重写父类中的纯虚函数,否则无法实例化对象Base* base = new Son;base->func();}int main() {system("pause");return 0;
}

4、案例2:制作饮品

案例描述:
制作饮品的大致流程为: 煮水 冲泡 倒入杯中 加入辅料
利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶

#include <iostream>
using namespace std;
#include <string>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) {//AbstractDrinking* abs=new Coffee;abs->makeDrink();delete abs;//释放		
}void test01() {//制作咖啡doWork(new Coffee);cout << "---------------" << endl;//制作茶叶doWork(new Tea);}int main() {test01();system("pause");return 0;
}


5、虚析构和纯虚析构 

虚析构和纯虚析构共性

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

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象
#include <iostream>
using namespace std;
#include <string>class Animal {
public:Animal() {cout << "Animal构造函数调用" << endl;}//利用虚析构可以解决 父类指针释放子类对象时不干净的问题/*virtual ~Animal(){cout<< "Animal虚析构函数调用" << endl;}*///纯虚析构 需要声明也需要实现virtual ~Animal() = 0;//纯虚函数virtual void speak() = 0;
};
Animal:: ~Animal() {cout << "Animal纯虚析构函数调用" << endl;
}class Cat :public Animal {
public:Cat(string name) {cout << "Cat构造函数调用" << endl;m_Name= new string(name);}virtual void speak() {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->speak();//父类指针在析构时候 不会调用子类中析构函数,导致子类如果有堆区属性,出现内存泄露delete animal;  
}int main() {test01();system("pause");return 0;
}

6、案例三:电脑组装

  • 电脑主要组成部件为 CPU (用于计算),显卡 (用于显示),内存条 (用于存储)
  • 将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Intel厂商和Lenovo厂商
  • 创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口
  • 测试时组装三台不同的电脑进行工作
#include <iostream>
using namespace std;
#include <string>//抽象不同零件类//抽象CPU类
class CPU {
public://抽象的计算函数virtual void calculate() = 0;};//抽象显卡类
class VideoCard {
public://抽象的显示函数virtual void display() = 0;};//抽象内存条类
class Memory {
public://抽象的存储函数virtual void storage() = 0;};//电脑类
class Computer {
public:Computer(CPU* cpu, VideoCard* vc, Memory* mem) {m_cpu = cpu;m_vc = vc;m_mem = mem;}//提供工作的函数void work() {//让零件工作起来,调用接口m_cpu->calculate();m_vc->display();m_mem->storage();}//提供析构函数 释放3个电脑零件~Computer() {//释放cpu零件if (m_cpu != NULL) {delete m_cpu;m_cpu = NULL;}//释放显卡零件if (m_vc != NULL) {delete m_vc;m_vc = NULL;}//释放内存条零件if (m_mem != NULL) {delete m_mem;m_mem = NULL;}}private:CPU* m_cpu;//CPU的零件指针VideoCard* m_vc;//显卡零件指针Memory* m_mem;//内存条零件指针
};//具体厂商
//Intel厂商
class IntelCPU :public CPU {
public:virtual void calculate() {cout << "Intel的CPU开始计算了" << endl;}
};class IntelVideoCard :public VideoCard {
public:virtual void display() {cout << "Intel的显卡开始显示了" << endl;}
};class IntelMemory :public Memory {
public:virtual void storage() {cout << "Intel的内存条开始存储了" << endl;}
};//Lenvo厂商
class LenvoCPU :public CPU {
public:virtual void calculate() {cout << "Lenvo的CPU开始计算了" << endl;}
};class LenvoVideoCard :public VideoCard {
public:virtual void display() {cout << "Lenvo的显卡开始显示了" << endl;}
};class LenvoMemory :public Memory {
public:virtual void storage() {cout << "Lenvo的内存条开始存储了" << endl;}
};void test01() {//第一台电脑零件CPU* intelCpu = new IntelCPU;VideoCard* intelCard = new IntelVideoCard;Memory* intelMem = new IntelMemory;cout << "第一台电脑开始工作" << endl;//创建第一台电脑Computer* computer1 = new Computer(intelCpu, intelCard, intelMem);computer1->work();delete computer1;cout << "---------------------" << endl;cout << "第二台电脑开始工作" << endl;//创建第二台电脑Computer* computer2 = new Computer(new LenvoCPU,new LenvoVideoCard,new LenvoMemory);computer2->work();delete computer2;cout << "---------------------" << endl;cout << "第三台电脑开始工作" << endl;//创建第三台电脑Computer* computer3 = new Computer(new LenvoCPU, new IntelVideoCard, new LenvoMemory);computer3->work();delete computer3;
}int main() {test01();system("pause");return 0;
}

相关文章:

多态(个人学习笔记黑马学习)

多态分为两类 静态多态: 函数重载和 运算符重载属于静态多态&#xff0c;复用函数名动态多态: 派生类和虚图数实现运行时多态 静态多态和动态多态区别: 静态多态的函数地址早绑定 编译阶段确定函数地址动态多态的函数地址晚绑定 运行阶段确定函数地址 1、基本语法 #include &…...

线程中future/atomic/async及nlohmann json的学习

1)std::future的其他成员函数 wait_for()成员函数&#xff0c;wait_for返回的是一个std::future_status枚举类型,根据返回值做相应处理 std::future_status state result.wait_for(std::chrono::seconds(1)); if(state std::future_status::ready) { cout<<result.get…...

windows安装MongoDB后进入命令交互界面失败解决方案

MongoDB下载链接&#xff1a;https://www.mongodb.com/download-center MongoDB安装教程&#xff1a;https://juejin.cn/post/6844903912000978952 不要安装最新的高版本MongoDB&#xff0c;因为配置方法可能会有差别&#xff0c;比如7.0一直失败的话就换5.0及以下版本试试&am…...

基于Java+SpringBoot+Vue前后端分离高校专业实习管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…...

E. Hanging Hearts

Problem - E - Codeforces 思路&#xff1a;我们考虑用树形dp&#xff0c;用f[i][0]表示以i为根&#xff0c;并且当前节点不在最长上升子序列中&#xff0c;用f[i][1]表示以i为根&#xff0c;当前节点在最长上升子序列中&#xff0c;那么f[i][0]max(f[j][0],f[j][1])&#xff0…...

docker安装RabbitMQ教程

可以通过Docker来安装RabbitMQ&#xff0c;具体步骤如下&#xff1a; 安装Docker&#xff1a;请参考官方文档进行安装。 拉取RabbitMQ镜像&#xff1a;通过以下命令拉取最新版本的RabbitMQ镜像。 docker pull rabbitmq:latest运行RabbitMQ容器&#xff1a;通过以下命令运行Rab…...

Java虚拟机整型数加载指令学习

JVM中 int 类型数值&#xff0c;根据 取值范围将 入栈的 字节码指令 就分为4类&#xff1a; 取值 -1~5 采用 iconst 指令&#xff1b; 取值 -128~127 采用 bipush 指令&#xff1b; 取值 -32768~32767 采用 sipush指令&#xff1b; 取值 -2147483648~2147483647 采用 ldc 指令。…...

Docker 实现 MySQL 一主一从配置

1、新建主服务器容器实例&#xff0c;端口&#xff1a; 3307 docker run \ -p 3307:3306 \ --name mysql-master \ -v /var/docker/mysql-master/log:/var/log/mysql \ -v /var/docker/mysql-master/data:/var/lib/mysql \ -v /var/docker/mysql-master/conf:/etc/mysql \ --p…...

Python编程练习与解答 练习113:避免重复

本练习将创建一个程序&#xff0c;从用户处读取单词&#xff0c;直到用户输入空行&#xff0c;在用户输入空行之后&#xff0c;程序应该显示一次用户输入的每个单词。单词应该按照他们最初的输入顺序显示。例如如果用户输入&#xff1a; first second first third second …...

线上 udp 客户端请求服务端客户端句柄泄漏问题

本题分别从如下三个方面来分享&#xff1a; 问题描述 自定义连接池的编写 common_pool 的使用 问题描述 线上有一个业务&#xff0c;某个通服务通知 udp 客户端通过向 udp 服务端&#xff08;某个硬件设备&#xff09;发送 udp 包来进行用户上线操作 当同时有大量的请求打到…...

合宙Air724UG LuatOS-Air LVGL API控件-窗口 (Window)

窗口 (Window) 分 享导出pdf 示例代码 win lvgl.win_create(lvgl.scr_act(), nil) lvgl.win_set_title(win, "Window title") -- close_btn lvgl.win_add_btn_right(win, "\xef\x80\x8d") -- --lvgl.obj_set_event_cb(cl…...

80 # 图片防盗链

referer 来源&#xff0c;表示这个资源被谁引用过&#xff0c;可以用来做防盗链。 我们新建文件 no-referer.js const fs require("fs"); const path require("path"); const url require("url"); const http require("http");h…...

App自动化测试持续集成效率提高50%

持续集成是一种开发实践&#xff0c;它倡导团队成员需要频繁的集成他们的工作&#xff0c;每次集成都通过自动化构建&#xff08;包括编译、构建、自动化测试&#xff09;来验证&#xff0c;从而尽快地发现集成中的错误。让正在开发的软件始终处于可工作状态&#xff0c;让产品…...

LeetCode —— 复写零(双指针)

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 将数组中出现的每个零复写一遍&#xff0c;然后将其他元素向右平移&#xff0c;数组长度不能改变。 法一&#xff1a;使用额外空间的做法 class Solution { public:void duplica…...

【Vue篇】Vue 项目下载、介绍(详细版)

如何创建一个vue项目&#xff1f;首先要有环境&#xff0c;如下&#xff1a; nodejs vue-cli如果有以上的工具就直接跳过安装教程 【Vue篇】mac上Vue 开发环境搭建、运行Vue项目&#xff08;保姆级&#xff09; 创建vue项目 选择一个位置&#xff0c;你要存放项目的路径&…...

Python批处理(一)提取txt中数据存入excel

Python批处理&#xff08;一&#xff09;提取txt中数据存入excel 问题描述 现从冠层分析软件中保存了叶面积指数分析的结果&#xff0c;然而软件保存格式为txt&#xff0c;且在不同的文件夹中&#xff0c;每个文件夹的txt文件数量不固定&#xff0c;但是txt文件格式固定。现需…...

只考一门数据结构!安徽工程大学计算机考研

安徽工程大学 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文992字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 安徽工程大…...

Ubuntu 20.04出现蓝牙无法打开的问题(已解决)

安装Ubuntu20.04后&#xff0c;蓝牙无法打开&#xff0c;按钮开启后蓝牙仍处于关闭状态 解决方法&#xff08;四种方式&#xff09; 1.卸载并重新加载btusb内核模块&#xff08;支持蓝牙设备的内核模块&#xff09; sudo rmmod btusb sleep 1 sudo modprobe btusb2、安装蓝牙工…...

并发测试工具 apache-jmeter使用发送post请求JSON数据

目录 1 下载安装 2 汉化 3 创建高并发测试 配置线程组 创建web请求 创建监听器 结果树 汇总报告 为web请求添加token 添加Content-Type用于发送json 4 启动测试 5 查看结果 1 下载安装 官网Apache JMeter - Download Apache JMeter 解压运行 2 2 汉化 打开软件…...

牛客练习赛115 A Mountain sequence

题目&#xff1a; 样例&#xff1a; 输入 3 5 1 2 3 4 5 3 3 3 3 3 1 2 1 输出 16 1 3 思路&#xff1a; 依据题意&#xff0c;再看数据范围&#xff0c;可以知道暴力肯定是不可能了&#xff0c;然后通过题目意思&#xff0c;我们可以排列模拟一下&#xff0c;这里排列所得结…...

5个关键场景下如何选择DINOv2模型:从ViT-S到ViT-G的完整指南

5个关键场景下如何选择DINOv2模型&#xff1a;从ViT-S到ViT-G的完整指南 【免费下载链接】dinov2 PyTorch code and models for the DINOv2 self-supervised learning method. 项目地址: https://gitcode.com/GitHub_Trending/di/dinov2 DINOv2是Meta AI Research开发的…...

3个步骤轻松下载B站视频:BilibiliDown全平台解决方案

3个步骤轻松下载B站视频&#xff1a;BilibiliDown全平台解决方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi…...

R语言clusterProfiler包KEGG富集分析报错?别慌,这份2024最新避坑指南帮你搞定

R语言clusterProfiler包KEGG富集分析2024避坑实战指南 当你在深夜的实验室里盯着RStudio不断弹出的红色报错信息&#xff0c;第十次尝试调整enrichKEGG参数却依然看到"replacement has length zero"这个令人绝望的提示时&#xff0c;可能已经忍不住要摔键盘了。这份…...

从零搭建CFD-DEM耦合环境:OpenFOAM与PFC3D在WSL2下的实战部署指南

1. 环境准备&#xff1a;WSL2与Ubuntu基础配置 第一次接触CFD-DEM耦合仿真的同学&#xff0c;建议从Windows系统起步。微软的WSL2&#xff08;Windows Subsystem for Linux&#xff09;现在已经能完美支持Ubuntu环境&#xff0c;实测比虚拟机流畅得多。我去年在联想小新Pro16上…...

使用 Taotoken 后如何通过用量看板清晰掌握各模型消耗与成本分布

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 使用 Taotoken 后如何通过用量看板清晰掌握各模型消耗与成本分布 当你在项目中接入多个大模型时&#xff0c;一个常见的困扰是成本…...

Win7/Win10 离线部署 VS2019 全流程实战与避坑指南

1. 离线部署VS2019的必要性与准备工作 在开发环境中&#xff0c;经常会遇到无法连接互联网的情况&#xff0c;比如企业内网隔离、保密项目开发或者老旧设备维护。这时候就需要离线安装Visual Studio 2019。我经历过多次这样的场景&#xff0c;特别是在给工厂车间的老旧Win7设备…...

Spinning Up模型保存终极指南:checkpoint管理完整教程

Spinning Up模型保存终极指南&#xff1a;checkpoint管理完整教程 【免费下载链接】spinningup An educational resource to help anyone learn deep reinforcement learning. 项目地址: https://gitcode.com/gh_mirrors/sp/spinningup 深度强化学习训练过程中&#xff…...

资源管理器老崩溃?可能是combase.dll在捣鬼,手把手教你用DISM和干净启动搞定它

深度解析Win10资源管理器崩溃&#xff1a;combase.dll故障诊断与系统级修复指南 当你在Windows 10中拖拽文件时突然遭遇黑屏闪烁&#xff0c;随后资源管理器自动重启&#xff0c;这种看似随机的崩溃往往与一个关键系统组件——combase.dll密切相关。作为COM基础库的核心文件&am…...

【AI面试临阵磨枪-56】大模型服务部署:Docker、K8s、GPU 调度、推理加速

一、 面试题目在生产环境中部署大模型服务时&#xff0c;你是如何结合 Docker 和 K8s 实现高效治理的&#xff1f;特别是在 GPU 调度&#xff08;如共享、切分&#xff09; 和 推理加速&#xff08;如 vLLM, TensorRT-LLM&#xff09; 方面有哪些实战经验&#xff1f;二、 知识…...

别再傻傻分不清了!WPF里Shape和Geometry到底该用哪个?实战避坑指南

WPF图形渲染进阶&#xff1a;Shape与Geometry的深度抉择与性能优化实战 在WPF开发中&#xff0c;图形渲染是构建丰富用户界面的核心能力之一。当开发者需要绘制自定义图形时&#xff0c;通常会面临选择Shape还是Geometry的难题。这个看似简单的选择背后&#xff0c;实际上涉及到…...