多态(虚构的整体,具体的个体)(多态的基本概念/多态的原理剖析/纯虚函数和抽象类/虚析构和纯虚析构)

多态的基本概念

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
// 多态的基本概念
// 多态分为静态多态和动态多态
// 静态多态: 函数重载还运算符重载属于静态多态,服用函数名
// 动态多态: 派生派和虚函数实现运行时多态//静态多态和动态多态的区别
// 静态多态的函数地址早绑定-编译阶段确定函数地址
// 动态多态的函数地址晚绑定-运行阶段确定函数地址// 动态多态满足条件
// 1.有继承关系
// 2.子类重写父类的虚函数
//    重写就是:函数返回值类型 函数名 参数列表 完全相同// 动态多态的使用
// 父类的指针或引用执行子类对象// 动物类
class Animal
{
public:virtual void speak(){cout << "动物在说话" << endl;}};
// 猫类
class Cat :public Animal
{
public:void speak(){cout << "小猫在说话" << endl;}
};// 执行说话的函数// C++中允许父子之间的类型转换,不需要强制类型转换
void doSpeak(Animal &animal)
{animal.speak();
}void test01()
{Cat c;// 属于地址早绑定,在编译阶段确定函数地址// 如果想执行让猫说话,那么这个函数地址就不能提前绑定。// 需要在运行期间绑定,地址晚绑定// 此时用到虚函数的概念,也就是在父类中的函数前加virtual// 此作用是让被调用的类的说话函数优先执行,起始也就是加virtual降低了本身的优先级// 子类中的virtual可写可不写doSpeak(c); // 相当于 Animal &animal = c;
}
void doSpeak(Animal* animal)
{animal->speak();
}
void test02()
{Cat c;doSpeak(&c);
}
int main()
{test01();// 引用test02();// 指针system("pause");return 0;
}

多态的原理剖析

此时该类中储存指向该函数的指针

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
// 多态的原理剖析
class Animal
{
public:virtual void speak(){cout << "动物在说话" << endl;};
};
class Cat :public Animal
{
public://重写之后void speak(){cout << "小猫在说话" << endl;}
};
int main()
{cout << "sizeof(Animal) = " << sizeof(Animal) << endl;system("pause");return 0;
}

多态案例一---- 计算器类

普通写法

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
// 计算器类普通写法
class Calculate
{
public:Calculate(int num1,int num2){this->num1 = num1;this->num2 = num2;}int doWork(string operate){if (operate == "+"){return num1 + num2;}else if (operate == "-"){return num1 - num2;}else if (operate == "*"){return num1 * num2;}// 此种写法如果想增加其它的功能,需要修改源码// 在真正的开发中 提倡 开闭原则// 开闭原则: 对扩展进行开放,对修改进行关闭}int num1;int num2;
};
// 普通写法
void test01()
{Calculate c(10, 20);cout << c.num1 << "+" << c.num2 << " = " <<  c.doWork("+") << endl;cout << c.num1 << "-" << c.num2 << " = " << c.doWork("-") << endl;cout << c.num1 << "*" << c.num2 << " = " << c.doWork("*") << endl;
}
int main()
{test01();system("pause");return 0;
}

多态写法

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
// 计算器类-多态写法// 多态的好处:
// 1.组织结构清晰
// 2.可读性强
// 3.对于前期和后期扩展以及维护性高// C++开发提倡利用多态设计程序架构,因为多态优点很多
class AbstractCalculate
{
public:int num1;int num2;virtual int calculate(){return 0;}
};
class Add :public AbstractCalculate
{
public:virtual int calculate(){return num1 + num2;}
};
class Del :public AbstractCalculate
{
public:virtual int calculate(){return num1 - num2;}
};
class Cheng :public AbstractCalculate
{
public:virtual int calculate(){return num1 * num2;}
};
void test01()
{// 多态使用条件// 父类指针或引用指向子类对象AbstractCalculate* c = new Add;c->num1 = 10;c->num2 = 20;cout << c->num1 << " + " << c->num2 << " = " << c->calculate() << endl;// 用完记得销魂delete c;c = new Del;c->num1 = 10;c->num2 = 20;cout << c->num1 << " - " << c->num2 << " = " << c->calculate() << endl;delete c;
}
int main()
{test01();system("pause");return 0;
}

纯虚函数和抽象类

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

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

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

抽象类特点:

1.无法实例化对象

2.子类必须重写抽象类中的纯虚函数,否则也属于抽象类

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;// 纯虚函数和抽象类
class Animal
{
public:// 纯虚函数// 只要有一个纯虚函数,这类就称为抽象类// 抽象类特点// 1.无法实例化对象// 2.子类必须重写父类中的纯虚函数,否则无法实例化对象virtual void func() = 0;};
class Cat :public Animal
{
public:void func(){cout << "func函数调用" << endl;}};
void test01()
{//Animal a;//new Animal;  //抽象类是无法实例化对象的Cat c;// 子类必须重写父类中的纯虚函数,否则无法实例化对象Animal& animal = c;animal.func();
}
int main()
{test01();system("pause");return 0;
}

多态案例二:制作饮品

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
class AbstraceMakeDrinking
{
public:// 1.煮水virtual void zhuShui() = 0;// 2.冲泡virtual void chongPao() = 0;// 3.倒入杯中virtual void daoRuBeiZhong() = 0;// 4.加入辅料virtual void jiaRuFuLiao() = 0;void makeDrink(){zhuShui();chongPao();daoRuBeiZhong();jiaRuFuLiao();}
};
class kaFei :public AbstraceMakeDrinking
{
public:// 1.煮水virtual void zhuShui(){cout << "煮咖啡水" << endl;}// 2.冲泡virtual void chongPao(){cout << "冲泡咖啡" << endl;}// 3.倒入杯中virtual void daoRuBeiZhong(){cout << "导入咖啡杯中" << endl;}// 4.加入辅料virtual void jiaRuFuLiao(){cout << "加入咖啡辅料" << endl;}
};
void test01()
{AbstraceMakeDrinking* coffee = new kaFei;coffee->makeDrink();delete coffee;
}
int main()
{test01();system("pause");return 0;
}

虚析构和纯虚析构

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
#include<string>
// 虚析构和纯虚析构
// 多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时
//无法调用到子类的析构代码
// 因为父类引用指向子类对象,故在释放空间时调用的是父类的析构函数
// 故使用多态(虚析构或纯虚析构)// 虚析构和纯虚析构的共性:
//  1.可以解决父类指针释放子类对象
//  2.都需要具体的函数实现// 虚析构和纯虚析构的区别:
//   如果是纯虚析构,该类属于抽象类,无法实例化对象// 总结
// 1.虚析构和纯虚析构就是用来解决父类指针释放子类对象
// 2.如果子类中没有堆区数据,可以不写虚析构或纯虚析构
// 3.拥有纯虚析构也属于抽象类
class Animal
{
public:// 纯虚析构virtual void speak() = 0;Animal(){cout << "Animal类构造函数的调用" << endl;}利用虚析构可以解决 父类指针释放子类对象时不干净的问题//virtual ~Animal()//{//	cout << "Animal类析构函数的调用" << endl;//}// 纯虚析构(需要声明也需要实现)// 有了纯虚析构之后,这个类也属于抽象类,无法实例化对象virtual ~Animal() = 0;
};
// 子类中需要析构函数释放空间,但是多态走不到子类中的析构函数,
// 所以需要虚析构和纯虚析构
Animal:: ~Animal()
{cout << "Animal类析构函数的调用" << endl;
}
class Cat :public Animal
{
public:string* name;Cat(string name){cout << "Cat类构造函数的调用" << endl;this->name = new string(name);}~Cat(){cout << "Cat类析构函数的调用" << endl;if (name != NULL){delete name;name = NULL;}}virtual void speak(){cout << *name << "小猫在说话" << endl;}
};
void test01()
{// 多态:父类指针或引用指向子类对象// 引用:给变量取别名Animal *animal = new Cat("Tom");animal->speak();// 父类指针在析构的时候,不回调用子类中析构函数,// 导致子类如果有堆区属性,出现内存泄露delete animal;animal = NULL;
}
int main()
{test01();system("pause");return 0;
}

    // 父类指针在析构的时候,不回调用子类中析构函数,
    // 导致子类如果有堆区属性,出现内存泄露

// 解决方法,将父类析构函数改为虚析构或纯虚析构

多态案例三: 电脑组装

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
using namespace std;
// CPU抽象类
class Cpu
{
public:virtual void calculate() = 0;
};
// 显卡抽象类
class DisplayCard
{
public:virtual void display() = 0;
};
// 内存抽象类
class Memory
{
public:virtual void distory() = 0;
};// 电脑类
class Computer
{
public:// 用来接受每一个零件Computer(Cpu *cpu, DisplayCard *card, Memory *memory){this->cpu = cpu;this->card = card;this->memory = memory;}~Computer(){if (cpu != NULL){delete cpu;cpu = NULL;}if (card != NULL){delete card;card = NULL;}if (memory != NULL){delete memory;memory = NULL;}}// 用来协同每一个零件工作void work(){cpu->calculate();card->display();memory->distory();}
private:Cpu* cpu;DisplayCard* card;Memory* memory;
};// 不同厂商的CPU
class IntelCpu :public Cpu
{
public:virtual void calculate(){cout << "Intel的CPU开始计算了" << endl;}
};
class LevoeCpu :public Cpu
{
public:virtual void calculate(){cout << "Levoe的CPU开始计算了" << endl;}
};// 不同厂商的显卡
class IntelDisplayCard :public DisplayCard
{
public:virtual void display(){cout << "Intel的显卡开始显示了" << endl;}
};
class LevoeDisplayCard :public DisplayCard
{
public:virtual void display(){cout << "Levoe的显卡开始显示了" << endl;}
};//不同厂商的内存条
class IntelMemory :public Memory
{
public:virtual void distory(){cout << "Intel的内存条开始存储了 " << endl;}
};
class LevoeMemory :public Memory
{
public:virtual void distory(){cout << "Levoe的内存条开始存储了 " << endl;}
};void test01()
{// 第一台电脑运行cout << "第一台电脑运行--------------------------" << endl;Cpu* cpu = new IntelCpu;DisplayCard* card = new IntelDisplayCard;Memory* memory = new IntelMemory;Computer *c = new Computer(cpu,card,memory);c->work();delete c;// 第二台电脑运行cout << "第二台电脑运行--------------------------" << endl;c = new Computer(new LevoeCpu, new LevoeDisplayCard, new LevoeMemory);c->work();delete c;c = NULL;
}
int main()
{test01();system("pause");return 0;
}

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

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

相关文章

VUE使用websocket

在之前搭建好的项目的基础上新版security demo&#xff08;二&#xff09;前端-CSDN博客 目录 一、代码改造 1、后端改造 2、VUE使用websocket 3、测试 二、按用户推送 1、完整代码如下 1.1、前端 1.2、后端&#xff1a; 2、测试 一、代码改造 1、后端改造 &#x…

逆波兰表达式

简介 介绍逆波兰表达式之前&#xff0c;先介绍一下运算种类。 中缀运算与后缀运算 中缀运算是一种常用的算术和逻辑公式表示方法&#xff0c;其中操作符位于两个运算数之间。例如&#xff0c;在表达式 “3 2” 中&#xff0c;加号&#xff08;&#xff09;是操作符&#xf…

算法设计:实验一分治与递归

【实验目的】 深入理解分治法的算法思想&#xff0c;应用分治法解决实际的算法问题。 【实验内容与要求】 设有n2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表&#xff1a; 1.每个选手必须与其他n-1个选手各赛一次&#xff1b;2.每个选手一天只能赛一…

Mysql 集群技术

目录 一 Mysql 在服务器中的部署方法 1.1 在Linux下部署mysql 1.1.1 安装依赖性并解压源码包&#xff0c;源码编译安装mysql&#xff1a; 1.1.2 部署mysql 二 mysql的组从复制 2.1 配置mastesr和salve 测试结果 2.2 当有数据时添加slave2 2.3 延迟复制 2.4 慢查询日志…

【C++ | 设计模式】简单工厂模式的详解与实现

1.简单工厂模式概述 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它定义了一个工厂类&#xff0c;由这个类根据提供的参数决定创建哪种具体的产品对象。简单工厂模式将对象的创建逻辑集中到一个工厂类中&#xff0c;从而将对…

Python-进阶-Excel基本操作

文章目录 Excel 基本操作1. 概述2. 写入2.1 使用 xlwt2.2 使用 XlsxWriter 3. 读取4. 修改 Excel 基本操作 1. 概述 在数据处理方面&#xff0c;Python 一直扮演着重要的角色&#xff0c;对于 Excel 操作&#xff0c;它有着完整且成熟的第三方库&#xff0c;使用也较为简单。…

视频结构化从入门到精通——认识视频结构化

认识视频结构化 1. 视频结构化与非结构化 1. 非结构化数据 非结构化数据指的是未经处理、以原始形式存在的数据。这类数据是直接采集、记录的&#xff0c;包含了音频、视频等多维信息&#xff0c;且没有任何标签、注释或分类来表示其中的内容。非结构化数据需要进一步处理和…

AI视频平台精选:国内外对比与推荐

原文&#xff1a;AI视频平台精选&#xff1a;国内外对比与推荐 国内外有多个平台可以生成AI视频&#xff0c;这些平台各有其独特的优点和缺点。以下是对一些主要平台的详细介绍&#xff0c;包括它们的优缺点&#xff0c;以及针对个人和自媒体用户的推荐。 国内平台 1. 快手可…

Android 架构模式之 MVVM

Android 架构 Android 架构模式之 MVCAndroid 架构模式之 MVPAndroid 架构模式之 MVVM 目录 Android 架构架构设计的目的对 MVVM 的理解代码ModelViewViewModel Android 中 MVVM 的问题试吃个小李子BeanModelViewViewModel效果展示 大家好&#xff01; 作为 Android 程序猿&a…

代码随想录算法训练营第13天 |二叉树的学习

目录 二叉树 理论基础 二叉树的分类 1. 满二叉树 (Full Binary Tree) 2. 完全二叉树 (Complete Binary Tree) 3. 平衡二叉树 (Balanced Binary Tree) 5. 二叉搜索树 (Binary Search Tree, BST) 二叉树的存储 1. 链式存储 (Linked Representation) 2. 顺序存储 (Sequent…

Golang | Leetcode Golang题解之第363题矩形区域不超过K的最大数值和

题目&#xff1a; 题解&#xff1a; import "math/rand"type node struct {ch [2]*nodepriority intval int }func (o *node) cmp(b int) int {switch {case b < o.val:return 0case b > o.val:return 1default:return -1} }func (o *node) rotate…

pyro 教程 时间序列 单变量,重尾,python pytorch,教程和实例 Forecasting预测,布朗运动项、偏差项和协变量项

预测I:单变量&#xff0c;重尾 本教程介绍了预测模块&#xff0c;用Pyro模型进行预测的框架。本教程只涵盖单变量模型和简单的可能性。本教程假设读者已经熟悉慢病毒感染和张量形状. 另请参见: 预测II:状态空间模型 预测三:层次模型 摘要 要创建预测模型: 创建预测模型班级…

算法笔试-编程练习-H-02-24

w这套题&#xff0c;侧重模拟和题目理解&#xff0c;只要按照题目描述正常复现整体分数应该不错 一、数据重删 数据重删是一种节约存储空间的技术&#xff0c;通常情况下&#xff0c;在数据存储池内是有很多重复的数据库。重删则是将这些重复的数据块找出并处理的技术。简单地…

Java:jdk8之后新增的时间API

文章目录 为什么要使用新增的API新增了哪些&#xff1f;Local常用方法代码一样的用法 黑马学习笔记 使用新增的 为什么要使用新增的API 新增了哪些&#xff1f; Local 常用方法 代码 package NewTime;import java.time.LocalDate;/*** Author: ggdpzhk* CreateTime: 2024-08-…

竞猜足球核心算法源码

需要实现的功能如下&#xff1a; 仅用于学习 竞猜足球核心算法源码 package com.lotterysource.portsadmin.service; import com.aliyun.oss.common.utils.DateUtil; import com.fasterxml.jackson.core.type.TypeReference; import com.lotterysource.portsadmin.dbprovid…

@ohos.systemParameterEnhance系统参数接口调用:控制设备硬件(执行shell命令方式)

本文介绍如何使用应用ohos.systemParameterEnhance (系统参数)(系统接口)来控制设备硬件&#xff0c;可以通过它在系统中执行一段shell命令&#xff0c;从而实现控制设备的效果。接下来以一个实际的样例来演示如何通过它来控制设备以太网接口 开源地址&#xff1a;https://git…

链表OJ题——环形链表2

文章目录 一、题目链接二、解题思路三、解题代码 一、题目链接 环形链表2 题目描述&#xff1a;在链表有环的基础上&#xff0c;找出环的入口点。 二、解题思路 三、解题代码

超实用的8个无版权、免费、高清图片素材网站整理

不管是设计、文章配图&#xff0c;还是视频制作&#xff0c;图片都至关重要。但是图片版权一直都是困扰很多设计、自媒体以及企业的大问题。现在&#xff0c;因为图片侵权被告的案例已经是司空见惯了&#xff0c;有的公众号甚至因为图片版权问题遭受致命打击。 1. Pexels Pexe…

(经验)SVN降版本,保留版本信息和用户信息。

背景&#xff1a;由于开始公司人数规模小&#xff0c;没有关心SVN最新版本免费对于用户数量限制要求不敏感&#xff0c;随着人数越来越多&#xff0c;公司来了新员工已经添加不了SVN需要注册码了&#xff0c;不利于SVN文件管理的在公司内部的推广。看了好多资料&#xff0c;都没…

信息学奥赛初赛天天练-75-NOIP2016普及组-完善程序-二分答案、二分查找、贪心算法、贪心策略

文章PDF链接: https://pan.baidu.com/s/1SVcGU_rApvoUWrUoviPCiA?pwdht2j 提取码: ht2j 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 1 完善程序 (单选题 &#xff0c;每小题3分&#xff0c;共30分) 郊游活动 有 n名同学参加学校组织的郊游活动&#xff0c…