C++多态(2) ——抽象类与final、override关键字

news2024/11/27 6:23:19

目录

一.抽象类 

        1.定义

        2.形式

3.举例:

解决方法:让子类重写纯虚函数,重写后子类就会变换为具体类,能够创建出对象了。

3.抽象类的作用

二.final与override关键字

        方法1:私有父类构造函数

方法2:私有父类的析构函数

2.1final关键字

        方法3:使用final关键字

final的真正用法:

2.2override关键字


一.抽象类 

        1.定义

       在有virtual修饰的虚函数的后面写上 = 0 ,则这个函数表示为纯虚函数。包含纯虚函数的类叫做抽象类,也叫做接口类,抽象类并不能实例化出对象,而且子类继承抽象父类后也不能实例化出对象。而解决方法:只有子类经过重写纯虚函数后,子类才能实例化出对象。纯虚函数规范了子类必须重写,另外纯虚函数更体现出了接口继承。

        

        2.形式

class <类名>{

public:

        virtual <类型><函数名>(<参数表>)=0; 

};

3.举例:

class Car {
public:
	virtual void Car_skill() = 0;
};

class Audi :public Car {

};

int main() {
	Car c;
	Audi a;
	return 0;
}

在上述代码中,新建了一个Car类,里面有一个虚函数,奇怪的是,这个虚函数设置=0了;继承Car类的子类Audi,和Car类在main函数中创建对象时,报错了。

        原因就是,Car类是抽象类,因为Car类中的Car_skill()函数是纯虚函数,虚函数是virtual,给虚函数加上=0就变成了纯虚函数了。


        根据概念可知:包含纯虚函数的类被称作是抽象类,抽象类是不能够实例化出对象的,而继承了Car类的子类Audi,Audi类也继承了父类的纯虚函数,那么Audi类也是抽象类,它也无法示例化出对象。

解决方法:让子类重写纯虚函数,重写后子类就会变换为具体类,能够创建出对象了。

class Car {
public:
	virtual void Car_skill() = 0;
};

class Audi :public Car {
	virtual void Car_skill() {
		cout << "加速性能好且操控感十足" << endl;
	}
};

int main() {
	//Car c;
	Audi a;		//此时子类Audi可以实例化出对象了,重写了从父类继承来的纯虚函数,那么Au'di也就不再是抽象类了
	return 0;
}

3.抽象类的作用

         虽然说抽象类不能定义对象, 但是可以定义指向抽象类数据的指针变量. 当子类成为具体类之后, 就可以用这种指针指向子类对象. 然后通过该指针调用虚函数, 实现多态性的操作。抽象类接口是面向对象程序设计中的核心概念, 是各种设计模式中必需的机制.

二.final与override关键字

在了解final关键字之前,我们先来聊聊一个类如何能不被子类所继承?

        其实,父类不让子类继承,最主要的办法就是封锁父类的构造函数,这样子类就算继承了父类,等到子类创建对象时,子类也无法调用父类的构造函数,子类也就无法给从父类那里继承来的成员变量赋值,实现了不被子类继承的目标。

        方法1:私有父类构造函数

class A {
private:
	A() {
	}
};

class B :public A {

};

int main() {
	B bb;
	return 0;
}

运行结果: 

方法2:私有父类的析构函数

class A {
public:
	A(int a)
	:_a(a) {
		cout << "A的构造函数" << endl;
	}

private:
	~A() {
		cout << "A的析构函数" << endl;
	}
public:
	int _a;
};

class B :public A {
public:
	B(int a=10, int b=5)
		:A(a)
		, _b(b) {
		cout << "B的构造函数" << endl;
			}
	
public:
	int _b;
};

int main() {
	B* ptr=new B;	//B类无法创建对象
	B b;			//这样,B类就无法使用A类继承过来的成员了
	//delete ptr;

	return 0;
}

        私有了父类的析构函数,即使子类对象能够调用父类的构造函数,也无法调用父类的析构函数,好比小说中的高燃台词:“假如你有能力创造这个强大的生命,但是你却无法永远的掌握它,也就没办法毁灭它,它的存在可能会威胁到我们,可能会导致生灵涂炭,世界毁灭,那么从一开始留不得它的存在!” 。编译器一开始就不会允许你这么做!所以该代码会报编译错误! 

 

还有第三种方式能够阻止子类继承父类。

2.1final关键字

        方法3:使用final关键字

	class A final{
	private:
		A()
		{}
	};
	

	class B : public A		// 无法从 "A" 继承,因为它已声明为 "final"	
	{};
	
	int main(){
		B bb;
		B* ptr = new B;
		return 0;
	}

使用final关键字修饰父类A,那么子类B就无法继承类A!报编译错误! 

final的真正用法:

//父类
class A {
public:
	 virtual void Sleep() final {		
		cout << "睡5个小时的觉" << endl;
	}
};

//子类
class B :public A {
	virtual  void Sleep() {
		cout << "睡5个小时的觉" << endl;
	}
};

在上边代码中,父类A的虚函数中加上了virtual关键字,在子类B继承了A类后,意味着该函数Sleep()不能被子类B重写,

2.2override关键字

class A {
public:
	virtual void Sleep() {
		cout << "睡5个小时的觉" << endl;
	}
};

//子类
class B :public A {
	  void Sleep(int i) override{
		cout << "睡5个小时的觉" << endl;
	}
};

override关键字的作用与final的相反,final是不想让子类重写父类的虚函数,而override是想让子类能够重写父类的虚函数,它的检查方式也是让系统进行检查

        如上图代码:A类中写了一个Sleep的虚函数,子类B中我想重写Sleep函数,加上了override,但是我写的Sleep函数并不是与父类A的Sleep完全相同的函数(函数参数不同),导致被override关键字检查出来了。

总结:

assert与final,override有异曲同工之妙,都是用来检查代码。

注:assert是在执行代码的过程中,由系统判断是否能够通过检查,检查报的是运行错误。


       而final,override是在编写代码的过程中就会让系统进行判断是否能通过检查,检查报的是编译错误:

        a. final的作用是让父类的函数不想要被子类重写,如果子类重写了该函数,则报错,该关键字用于放置在父类的函数定义末尾。

        b.override的作用是父类想让子类确保能够重写父类的函数,如果没有重写,则报错。该关键字用于放置在子类重写的虚函数定义末尾处。

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

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

相关文章

Linux - 进程控制(创建和终止)

1.进程创建 fork函数初识 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 返回值&#xff1a;子进程返回0&#xff0c;父进程返回子进程id&#xff0c;出错返回-1 getpid()获取子进程id&#xf…

JVM、Redis、反射

JVM JVM是Java virtual machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一种用于计算机的规范&#xff0c;是通过在实际计算机上仿真模拟各种计算机功能来实现的。 主要组件构成&#xff1a; 1.类加载器 子系统负责从文件系统或者网络中加载Class文件&…

分布式文件存储与数据缓存 Redis高可用分布式实践(下)

六、Redisweb实践 网页缓存 1.创建springboot项目 2.选择组件 Lombok spring mvc spring data redis spring data jpa 3.编写配置文件 ### 数据库访问配置 spring.datasource.driver-class-namecom.mysql.jdbc.Driver spring.datasource.urljdbc:mysql://192.168.66.100:3307/…

uniapp scroll-view显示滚动条

在style中添加样式&#xff1a; ::v-deep ::-webkit-scrollbar {/* 滚动条整体样式 */display: block;width: 10rpx !important;height: 10rpx !important;-webkit-appearance: auto !important;background: transparent;overflow: auto !important;}::v-deep ::-webkit-scroll…

matlab使用教程(6)—线性方程组的求解

进行科学计算时&#xff0c;最重要的一个问题是对联立线性方程组求解。在矩阵表示法中&#xff0c;常见问题采用以下形式&#xff1a;给定两个矩阵 A 和 b&#xff0c;是否存在一个唯一矩阵 x 使 Ax b 或 xA b&#xff1f; 考虑一维示例具有指导意义。例如&#xff0c;方程 …

测试|自动化测试(了解)

测试|自动化测试&#xff08;了解&#xff09; 1.什么是自动化测试☆☆☆☆ 自动化测试相当于把人工测试手段进行转换&#xff0c;让代码执行。 2.自动化测试的分类☆☆☆☆ 注&#xff1a;这里只是常见的自动化测试&#xff0c;并不全部罗列。 1.单元自动化测试 其中Java…

分布式开源监控Zabbix实战

Zabbix作为一个分布式开源监控软件&#xff0c;在传统的监控领域有着先天的优势&#xff0c;具备灵活的数据采集、自定义的告警策略、丰富的图表展示以及高可用性和扩展性。本文简要介绍Zabbix的特性、整体架构和工作流程&#xff0c;以及安装部署的过程&#xff0c;并结合实战…

数据结构 | Radix Tree 树

什么是基数树&#xff1f; 基数树是一种多叉搜索树&#xff0c;数据位于叶子节点上&#xff0c;每一个节点有固定的2^n个子节点&#xff08;n为划分的基大小&#xff0c;当n为1时&#xff0c;为二叉树&#xff09;。 什么为划分的基&#xff1f; 以一个64位的长整型为例&#x…

oracle 19c打补丁遭遇OPATCHAUTO-72043OPATCHAUTO-68061

最近&#xff0c;在AIX上的新装oracle 19C数据库基础版本&#xff0c;使用opatchauto打PSU补丁集35037840时遇到了OPATCHAUTO-72043报错&#xff0c;无法正常应用GI补丁。 一、环境描述 操作系统&#xff1a;AIX 数据库版本&#xff1a;oracle rac 19.3.0新装基础版 应用PS…

代码随想录第四十八天|198、213、337.打家劫舍

198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个…

【JAVASE】重载与递归

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈java &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 重载与递归 1. 方法重载1.1 为什么需要方…

开源代码分享(9)—面向100%清洁能源的发输电系统扩展规划(附matlab代码)

1.背景介绍 1.1摘要 本文提出了一种新颖的建模框架和基于分解的解决策略&#xff0c;将随机规划&#xff08;SP&#xff09;和鲁棒优化&#xff08;RO&#xff09;相结合&#xff0c;以应对协调中长期电力系统规划中的多重不确定性。从独立系统运营商&#xff08;ISO&#xff…

CAD曲面建模

首先还是要在3d绘图的环境中进行 在网络菜单栏的左侧&#xff0c;有曲面建模相关的功能 包括旋转形成曲面、平移形成曲面&#xff0c;按照两条线形成网格&#xff0c;按照四条封闭的线形成曲面等等 首先演示旋转曲面 需要被旋转的对象&#xff0c;以及旋转轴 首先选择要旋转…

Leetcode | DP | 338. 198. 139.

338. Counting Bits 重点在于这张图。 从i1开始&#xff0c;dp的array如果i是2的1次方之前的数&#xff0c;是1 dp[i - 2 ^ 0]; 如果i是2的2次方之前的数&#xff0c;是1 dp[i - 2 ^ 1]; 如果i是2的3次方之前的数&#xff0c;是1 dp[i - 2 ^ 2]; 198. House Robber 如果…

Hadoop学习指南:探索大数据时代的重要组成——Hadoop运行模式(下)

Hadoop运行模式(下&#xff09; 前言2.6 配置历史服务器1&#xff09;配置mapred-site.xml2&#xff09;分发配置3&#xff09;在hadoop102启动历史服务器4&#xff09;查看历史服务器是否启动5&#xff09;查看JobHistory 2.7 配置日志的聚集1&#xff09;配置yarn-site.xml2&…

【ChatGPT辅助学Rust | 基础系列 | Rust初相识】Rust简介与环境配置

教程目录 前言一&#xff0c;Rust简介1&#xff0c;Rust的历史2&#xff0c;Rust的特性3&#xff0c;为什么选择Rust4&#xff0c;Rust可以做什么 二&#xff0c; Rust环境配置1&#xff0c;windows11安装2&#xff0c;Linux安装 三&#xff0c;安装IDE 前言 Rust是一种系统编…

智慧水务配电能效系统的开发与功能介绍

随着城市化进程的步伐大大变快&#xff0c;城市建设与科学信息技术的融合程度也在不断提升&#xff0c;尤其是大数据信息技术的迅猛发展&#xff0c;为民生工程由信息化向智能化转型提供了条件。以城市的水务系统为例&#xff0c;依托大数据信息技术构建智慧水务系统是智慧城市…

从 DejaVu 改为 Noto,Ubuntu 23.10 发行版计划调整字体包

近日消息&#xff0c;代号为“Mantic Minotaur”的 Ubuntu 23.10 发行版计划调整字体包&#xff0c;从 DejaVu 修改为 Noto。 近日消息&#xff0c;代号为“Mantic Minotaur”的 Ubuntu 23.10 发行版计划调整字体包&#xff0c;从 DejaVu 修改为 Noto。 Ubuntu 开发团队表示为…

数字人第一剑,先斩“尹天仇”

第一波被数字人抢走饭碗的人类&#xff0c;不是带货主播&#xff0c;也不是虚拟偶像&#xff0c;而是好莱坞的群演们。 过去几个月&#xff0c;数千名好莱坞演员罢工&#xff0c;并出现在Netflix奈飞、华纳兄弟、Discovery、亚马逊、派拉蒙和NBC环球的办公大楼示威。 此次好莱坞…

哈工大计算机网络课程网络安全基本原理详解之:密钥分发中心与公钥认证中心

哈工大计算机网络课程网络安全基本原理详解之&#xff1a;密钥分发中心与公钥认证中心 在介绍密钥分发中心的概念前&#xff0c;先来回顾一下之前介绍的身份认证协议AP4.0&#xff1a;利用随机数R来避免“回放攻击”&#xff0c;并借助于对称加密算法来保证R的加密传输和解密&…