关于多态~

多态的基本概念

多态是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.mzph.cn/diannao/7740.shtml

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

相关文章

基于CLAHE算法的图像增强及评价

摘要&#xff1a; 本研究旨在探讨对比度限制自适应直方图均衡化&#xff08;CLAHE&#xff09;算法在数字图像处理中的应用。CLAHE算法通过在局部区域内进行直方图均衡化&#xff0c;有效地增强了图像的对比度&#xff0c;并在保持图像细节的同时避免了过度增强的问题。本文通过…

Eclipse 开创性地集成 Neon Stack,将 EVM 兼容性带到 SVM 网络

2024年5月2日&#xff0c;全球——在塑造区块链网络的战略联盟的过程中&#xff0c;Eclipse 通过集成 Neon EVM 核心团队开发的技术堆栈 Neon Stack&#xff0c;成为首个打破 EVM-SVM 兼容性障碍的生态。 Eclipse 旨在通过结合以太坊和 Solana 的最佳特性&#xff0c;来重构区…

mksh静态编译

代码来源&#xff1a;https://github.com/MirBSD/mksh.git 需求&#xff0c;基于musl库编译一个静态可执行文件&#xff0c;验证 musl库是否正常 根据 Build.sh文件定义&#xff0c;可以设置 LDFLAGS, CFLAGS,LIBS等参数 1. 首先编译musl ./configure --enable-debugyes --…

java 继承和静态属性或方法

目录 继承 静态属性和方法 继承与静态属性或方法的关系&#xff1a; 示例&#xff1a; 注意&#xff1a; PS&#xff1a;如有错漏之处&#xff0c;敬请指正 在Java中&#xff0c;继承和静态属性或方法是面向对象编程中的两个重要概念。它们在类设计和使用中扮演着不同的角…

数据结构(c):队列

目录 &#x1f37a;0.前言 1.什么是队列 2. 队列的实现 2.1定义队列节点 2.2定义队列 2.3队尾入队列 2.4判断队列是否为空 2.5队头出队列 2.6 队列首元素 2.7队尾元素 2.8队列内的元素个数 2.9销毁队列 3.试运行 &#x1f48e;4.结束语 &#x1f37a;0.前言 言C之…

Partisia Blockchain 生态首个zk跨链DEX现已上线

在5月1日&#xff0c;由Partisia Blockchain与zkCross创建合作推出的Partisia zkCrossDEX在Partisia Blockchain生态正式上线。Partisia zkCrossDEX是Partisia Blockchain上重要的互操作枢纽&#xff0c;其融合了zkCross的zk技术跨链互操作方案&#xff0c;并利用Partisia Bloc…

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

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

Linux命名管道的创建及应用

目录 一、命名管道的定义即功能 1.1创建命名管道 1.2匿名管道和命名管道的区别 1.3命名管道的打开规则 1.4系统调用unlink 二、进程间命名管道的创建及使用 2.1Comm.hhp 2.2PipeServer.cc 2.3PipeClient.cc 一、命名管道的定义即功能 管道应用的一个限制就是只能在具有…

[报错解决]SpringBoot子项目打jar包启动报 XXX--1.0-SNAPSHOT.jar中没有主清单属性

目录 报错信息解决原因原因分析解决方案 报错信息 解决 原因 在使用SpringBoot架构搭建父子工程时&#xff0c;使用IDEA可以正常启动&#xff0c;对子项目打成jar包后使用jar方式启动时&#xff0c;会报错xx.jar中没有主清单属性。 原因分析 原因主要是在使用jar方式启动时…

鸿蒙OpenHarmony南向:【Hi3516标准系统入门(命令行方式)】

Hi3516标准系统入门&#xff08;命令行方式&#xff09; 注意&#xff1a; 从3.2版本起&#xff0c;标准系统不再针对Hi3516DV300进行适配验证&#xff0c;建议您使用RK3568进行标准系统的设备开发。 如您仍然需要使用Hi3516DV300进行标准系统相关开发操作&#xff0c;则可能会…

javaweb学习笔记1

1、基本概念 1.1、前言 web开发&#xff1a; web&#xff0c;网页的意思&#xff0c;www.baidu.com 静态web html,css 提供给所有人看的数据始终不会发生变化&#xff01; 动态web 淘宝&#xff0c;几乎是所有的网站&#xff1b; 提供给所有人看的数据始终会发生变化&…

GMS地下水数值模拟及溶质(包含反应性溶质)运移模拟技术

采用全流程模式将地下水数值模拟软件GMS的操作进行详细剖析和案例联系。不仅使学员掌握地下水数值模拟软件GMS的全过程实际操作技术的基本技能&#xff0c;而且可以深刻理解模拟过程中的关键环节&#xff0c;以解决实际问题能力。同时为满足环评从业人员进一步加强地下水数值模…

typescript 中的泛型

泛型&#xff1a;解决 类、接口、方法的复用性、以及对不特定数据类型的支持 传入的参数与返回参数类型一致 泛型函数 // T表示泛型&#xff0c;具体什么类型是调用这个方法的时候决定的 function getData<T>(value: T): T {return value } getData<number>(123) …

Linux生成密钥对并配置免密访问

(1) 在客服端生成密钥对 先生成私钥&#xff0c;再生成公钥 ssh-keygen ---生成密钥对命令 Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): --保存密钥对路径 Enter passphrase (empty for no passphrase): 输入…

腾讯突然宣布,微信鸿蒙版要来了!

今年初&#xff0c;华为宣布HarmonyOS NEXT命名为“鸿蒙星河版”&#xff0c;并计划在二季度启动开发者 Beta 计划&#xff0c;四季度发布商用正式版。 消息一出&#xff0c;不少人为之振奋。 鸿蒙星河版因不再兼容安卓开源应用&#xff0c;仅支持鸿蒙内核和系统的应用&#x…

Penpad再获 Presto Labs 投资,Scroll 生态持续扩张

Penpad是Scroll生态的LaunchPad平台&#xff0c;其整计划像收益聚合器以及RWA等功能于一体的综合性Web3平台拓展&#xff0c;该平台在近期频获资本市场关注&#xff0c;并获得了多个知名投资者/投资机构的支持。 截止到本文发布前&#xff0c;Penpad已经获得了包括Scroll联合创…

(三)JSP教程——JSP动作标签

JSP动作标签 用户可以使用JSP动作标签向当前输出流输出数据&#xff0c;进行页面定向&#xff0c;也可以通过动作标签使用、修改和创建对象。 <jsp:include>标签 <jsp:include>标签将同一个Web应用中静态或动态资源包含到当前页面中。资源可以是HTML、JSP页面和文…

静态库和动态库的了解

静态库和动态库是程序开发中常用的两种库文件类型&#xff0c;它们各有特点&#xff0c;适用于不同的场景。下面是对它们的基本概念、优缺点以及使用场景的概述&#xff1a; 静态库 概念&#xff1a;静态库是一组预先编译好的函数和数据的归档集合&#xff0c;通常以.a&#x…

B端UX/UI设计面试作品集分层源文件figmasketch模板

当您考虑找工作时&#xff0c;是否曾质疑过项目复盘作品集的重要性&#xff1f;实际上&#xff0c;一份精心准备的项目复盘作品集对于求职者来说具有无可估量的价值&#xff0c;特别是对于设计师这一职业领域。 以下所述或许对您而言已非陌生。您的作品集应当成为您专业技能与…

为什么BGP用于建立对等体关系的环回口主机路由通过BGP传递不优

BGP用于建立对等体关系的环回口主机路由通过BGP传递不优 问题描述&#xff1a; R1和R2通过环回口建立BGP对等体关系 R1在BGP进程中&#xff0c;又network了该环回口地址的主机路由 此时&#xff0c;在R2的bgp routing-table&#xff08;BGP协议路由表&#xff09;中&#x…