多态相关知识2

news2024/11/15 12:31:58

多态相关知识2

  • 抽象基类和纯虚函数
  • 纯虚函数和多继承
  • 虚析构函数
    • 虚析构函数作用
    • 纯虚析构函数
  • 重写 重载 重定义

抽象基类和纯虚函数

在设计时,常常希望基类仅仅作为其派生类的一个接口。这就是说,仅想对基类进行向上类型转换,使用它的接口,而不希望用户实际的创建一个基类的对象。同时创建一个纯虚函数允许接口中放置成员原函数,而不一定要提供一段可能对这个函数毫无意义的代码。

做到这点,可以在基类中加入至少一个纯虚函数(pure virtual function),使得基类称为抽象类(abstract class).

  1. 纯虚函数使用关键字virtual,并在其后面加上=0。如果试图去实例化一个抽象类,编译器则会阻止这种操作。
  2. 当继承一个抽象类的时候,必须实现所有的纯虚函数,否则由抽象类派生的类也是一个抽象类。
  3. Virtual void fun() = 0;告诉编译器在vtable中为函数保留一个位置,但在这个特定位置不放地址。

建立公共接口目的是为了将子类公共的操作抽象出来,可以通过一个公共接口来操纵一组类,且这个公共接口不需要事先(或者不需要完全实现)。可以创建一个公共类.

案例: 模板方法模式
在这里插入图片描述

//抽象制作饮品
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 DoBussiness(AbstractDrinking* drink){
	drink->MakeDrink();
	delete drink;
}

void test(){
	DoBussiness(new Coffee);
	cout << "--------------" << endl;
	DoBussiness(new Tea);
}

纯虚函数和多继承

多继承带来了一些争议,但是接口继承可以说一种毫无争议的运用了。
绝大数面向对象语言都不支持多继承,但是绝大数面向对象对象语言都支持接口的概念,c++中没有接口的概念,但是可以通过纯虚函数实现接口。

接口类中只有函数原型定义,没有任何数据定义。

多重继承接口不会带来二义性和复杂性问题。接口类只是一个功能声明,并不是功能实现,子类需要根据功能说明定义功能实现。

注意:除了析构函数外,其他声明都是纯虚函数。
在这里插入图片描述

在这里插入图片描述

虚析构函数

虚析构函数作用

虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

class People{
public:
	People(){
		cout << "构造函数 People!" << endl;
	}
	virtual void showName() = 0;
	virtual ~People(){
		cout << "析构函数 People!" << endl;
	}
};

class Worker : public People{
public:
	Worker(){
		cout << "构造函数 Worker!" << endl;
		pName = new char[10];
	}
	virtual void showName(){
		cout << "打印子类的名字!" << endl;
	}
	~Worker(){
		cout << "析构函数 Worker!" << endl;
		if (pName != NULL){
			delete pName;
		}
	}
private:
	char* pName;
};

void test(){

	People* people = new Worker;
	people->~People();
}

纯虚析构函数

纯虚析构函数在c++中是合法的,但是在使用的时候有一个额外的限制:必须为纯虚析构函数提供一个函数体。

那么问题是:如果给虚析构函数提供函数体了,那怎么还能称作纯虚析构函数呢?

纯虚析构函数和非纯析构函数之间唯一的不同之处在于纯虚析构函数使得基类是抽象类,不能创建基类的对象。

//非纯虚析构函数
class A{
public:
	virtual ~A();
};

A::~A(){}

//纯析构函数
class B{
public:
	virtual ~B() = 0;
};

B::~B(){}

void test(){
	A a; //A类不是抽象类,可以实例化对象
	B b; //B类是抽象类,不可以实例化对象
}

如果类的目的不是为了实现多态,作为基类来使用,就不要声明虚析构函数,反之,则应该为类声明虚析构函数。

重写 重载 重定义

重载,同一作用域的同名函数

  1. 同一个作用域
  2. 参数个数,参数顺序,参数类型不同
  3. 和函数返回值,没有关系
  4. const也可以作为重载条件 //do(const Teacher& t){} do(Teacher& t)

重定义(隐藏)

  1. 有继承
  2. 子类(派生类)重新定义父类(基类)的同名成员(非virtual函数)

重写(覆盖)

  1. 有继承
  2. 子类(派生类)重写父类(基类)的virtual函数
  3. 函数返回值,函数名字,函数参数,必须和基类中的虚函数一致
class A{
public:
	//同一作用域下,func1函数重载
	void func1(){}
	void func1(int a){}
	void func1(int a,int b){}
	void func2(){}
	virtual void func3(){}
};

class B : public A{
public:
	//重定义基类的func2,隐藏了基类的func2方法
	void func2(){}
	//重写基类的func3函数,也可以覆盖基类func3
	virtual void func3(){}
};

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

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

相关文章

Wing FTP Server

文章目录 1.Wing FTP Server简介1.1主要特点1.2使用教程 2.高级用法2.1Lua脚本,案例1 1.Wing FTP Server简介 Wing FTP Server&#xff0c;是一个专业的跨平台FTP服务器端&#xff0c;它拥有不错的速度、可靠性和一个友好的配置界面。它除了能提供FTP的基本服务功能以外&#…

据阿谱尔APO Research统计,2023年全球皮肤科药物市场价值为 751.7 亿美元

据阿谱尔 (APO Research&#xff09;统计&#xff0c;2023 年全球皮肤科药物市场价值估计为 751.7 亿美元&#xff0c;预计到 2030 年将达到 1622.1 亿美元&#xff0c;预测期内&#xff08;2024-2030 年&#xff09;的复合年增长率为 11.44%。 全球最大的单一类别皮肤科药物是…

TheBrain 14:AI增强的视觉知识管理工具

TheBrain是一款与众不同的思维导图软件&#xff0c;其所有信息通过一个又一个的节点进行联系&#xff0c;最终形成一个杂而不乱的网状结构。与传统的树形思维导图相较而言&#xff0c;TheBrain更有助于整合零散的资源&#xff0c;激发创意和锻炼思维。此次thebrain13带来了很多…

基因组学系列3:基因分型Phasing与单倍型参考序列HRC

1. 基因分型Phasing概念 基因分型&#xff0c;也称为基因定相、单倍体分型、单倍体构建等&#xff0c;即将一个二倍体&#xff08;或多倍体&#xff09;基因组上的等位基因&#xff08;或杂合位点&#xff09;正确定位到父亲或母亲的染色体上&#xff0c;最终使得来自同一亲本…

HMI 的 UI 风格成就经典

HMI 的 UI 风格成就经典

【自动驾驶仿真在做什么——初学者总结(陆续补充)】

文章目录 基础概念自动驾驶级别再稍提一下ODD是什么&#xff1f; 自动驾驶仿真分类软件在环仿真硬件仿真 仿真究竟难在哪&#xff1f;一些名词解释 最近也是学习自动驾驶仿真相关知识&#xff0c;习惯去总结一下&#xff0c;方便自己回顾和总结&#xff0c;主要包括了自动驾驶框…

登 Cell 子刊!清华大学张强锋课题组开发 SPACE 算法,组织模块发现能力领先同类工具

多细胞生物中的细胞尽管共享相同的基因组&#xff0c;但因其内部基因调控网络的差异以及与周围微环境中相邻细胞的外部信号交流&#xff0c;使得它们在形态、基因表达和功能上展现出显著的多样性。为了将细胞类型信息与其在组织内的空间位置相关联&#xff0c;空间转录组学 (Sp…

OpenLCA、GREET、R语言的生命周期评价方法、模型构建

原文链接&#xff1a;OpenLCA、GREET、R语言的生命周期评价方法、模型构建教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247608240&idx6&sn1b5758206d500399fe7cc69e800f61fe&chksmfa826657cdf5ef413d31557941a1c5db5cc84bba8d0f408c469e05a4118c…

软考的报名详细流程

2024年软考的考试时间已经公布&#xff0c;分别为5月25日至28日和11月9日至12日。准备参加2024年软考的朋友们&#xff0c;一定要提前关注官方发布的考试安排。 本文将详细介绍软考报考的整个流程。准备报考的朋友们&#xff0c;阅读本文就足够啦&#xff01;软考的报考流程大致…

Vant Design - VUE 时间区间限制

效果图&#xff0c;限制7天 实现代码 <a-range-picker v-model"dateTime" style"width: 100%" :disabled-date"disabledDate" format"YYYY-MM-DD HH:mm:ss" :showTime"true" :placeholder"[开始时间, 结束时间]&quo…

Vue 解决报错 VM6290:1 Uncaught SyntaxError: Unexpected identifier ‘Promise‘

Vue 报错 VM6290:1 Uncaught SyntaxError: Unexpected identifier ‘Promise’ 排查 控制台报了一个错误 , Uncaught SyntaxError: Unexpected identifier ‘Promise’&#xff0c;网上查到的方法是 缺少符号&#xff0c;语法写法错误&#xff0c;但这些都没有解决我的问题&am…

Simulink 模型生成 C 代码(三):将模型参数配置为全局变量以在运行时调整

默认情况下&#xff0c;代码生成优化可避免存储不参与入口函数接口的模型参数和大多数信号。要使参数可调和相关信号可访问&#xff0c;请通过显式配置方式来标识它们。 在模型 RollAxisAutopilot 的 BasicRollMode 子系统中&#xff0c;将 PID 控制参数配置为在代码中显示为可…

VMware Workstation桥接模式无法上网

问题背景 我之前创建过一个虚拟机&#xff0c;当时虚拟机的网络模式使用的是桥接模式&#xff0c;配置好了固定ip地址&#xff0c;是可以正常上网的&#xff0c;中间没有做任何网络上面的配置。但是今天再打开这台虚拟机时&#xff0c;发现竟然不能上网了。 物理主机的ip信息配…

构造函数深入理解

目录 构造函数构造函数体赋值初始化列表初始化列表格式初始化列表的意义以及注意点const修饰的成员变量初始化对象成员具体初始化的地方缺省值存在的意义例子1例子2 初始化与赋值引用成员变量的初始化注意点1注意点2我的疑惑 自定义类型成员初始化例子1例子2例子3例子4 初始化列…

JAVA小知识31:多线程篇2

一、等待唤醒机制 生产者和消费者&#xff0c;也叫等待唤醒机制。他是一个十分经典的多线程协作的模式。我们来讲一个小故事&#xff1a; 在一个繁忙的工厂里&#xff0c;有一个生产线&#xff0c;我们称之为“共享资源”。这个生产线一次只能生产一个产品&#xff0c;而且需要…

Stable Diffusion【基础篇】:降噪强度(denoising strength)

提到降噪强度&#xff08;denoising strength&#xff09;&#xff0c;大家一定不会陌生&#xff0c;这个参数是图生图中最关键的参数之一。今天在Stable Diffusion Art网站看到一篇介绍降噪强度&#xff08;denoising strength&#xff09;的文章&#xff08;地址&#xff1a;…

HMI 的 UI 风格创新无限

HMI 的 UI 风格创新无限

「实战应用」如何用图表控件LightningChart JS创建SQL仪表板应用(三)

LightningChart JS是Web上性能特高的图表库&#xff0c;具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用&#xff0c;从而实现高刷新率和流畅的动画&#xff0c;常用于贸易&#xff0c;工程&#xff0c;航…

从零开始:AI产品经理的入门路线图

引言&#xff1a; 想象这样一个场景&#xff1a;早晨的阳光穿透窗帘&#xff0c;投射在新一代智能机器人上&#xff0c;它正静静等待着你的第一个命令开始全新的一天。这样的场景听起来像是科幻小说里的情节&#xff0c;但实际上&#xff0c;这正是AI产品经理们工作的成果。如…

数字人直播源码开发全攻略揭秘:如何搭建自己的数字人直播平台?

当前&#xff0c;数字人直播逐渐成为众多中小型企业线上带货和品牌宣传的不二之选&#xff0c;而艾媒研究数据也显示&#xff0c;超五成以上的被调查群体的企业使用过虚拟人技术&#xff0c;超三成被调查群体的企业计划使用虚拟人技术。在此背景下&#xff0c;越来越多的创业者…