C++|多态性与虚函数(2)|虚析构函数|重载函数|纯虚函数|抽象类

前言

看这篇之前,可以先看多态性与虚函数(1)⬇️

C++|多态性与虚函数(1)功能绑定|向上转换类型|虚函数-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_74197067/article/details/138861418?spm=1001.2014.3001.5501这篇文章会接着上一篇来记录

虚析构函数

构造函数不能是虚函数,但析构函数可以是虚函数,同样的在析构函数前面加上virtual就 称该析构函数为虚析构函数,语法如下:

virtual ~类名() 

{

        函数体

}

#include<iostream>
using namespace std;class point
{
public:point():x(0),y(0){}point(double a, double b) :x(a), y(b) {}virtual ~point(){cout << "~point" << endl;}double x;double y;};class rectangle :public point
{
public:rectangle():point(0,0),x1(0),y1(0){}rectangle(double a, double b, double c, double d) :point(a, b), x1(c), y1(d) {}~rectangle(){cout << "~rectangle" << endl;}
private:double x1;double y1;
};int main()
{point* p = nullptr;p = new rectangle;delete p;return 0;
}

就会先调用rectangle 的析构函数,在调用point的析构函数。如果在基类的析构函数中不加virtual,那么运行结果只会调用point的析构函数

如果将基类的虚构函数写为虚函数,那么后面所有继承该基类的派生类的所有析构函数自动成为虚函数,即使名字不相同。

当基类的析构函数为虚函数时,无论指针指向的是同一类族那个类的对象,程序都会动态关联,调用相应的析构函数,对该对象所涉及的额外内存空间进行清理工作。

最好把基类的析构函数声明为虚函数,这使得后面派生类所有的析构函数均为虚函数,这样如果调用delete运算符准备删除一个对象,而delete运算符的操作对象用了派生类对象的基类指针,系统就会先调用派生类的析构函数,在调用基类的析构函数,这样整个派生类的对象被完全释放。

虚函数与重载函数比较

函数重载处理的是同一层次的函数重名问题,

而虚函数处理的是同一类族中不同派生层次 上的函数重名问题

函数重载时,参数个数和参数类别可以不一样

虚函数必须保证同名,同参数,同返回值

函数重载可以是成员函数也可以普通函数

虚函数只能是成员函数

函数重载的调用是以所传递参数序列的差别作为调用不同函数的依据

虚函数是根据对象的不同去调用不同类的虚函数

函数重载在编译时表现出多态性

虚函数在运行时表现多态性

纯虚函数

有时,基类往往表示一种抽象的概念,并不与其他事物相连,例如,封闭图形只是一个概念,但他可以派生出,三角形、四边形、五边形...

纯虚函数与一般虚函数定义格式基本相同,只是在后面多了”=0“部分表示没有函数体部分,纯虚函数的函数体由派生类给出

纯虚函数的定义形式如下:

class 类名

{

        ...

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

        ...

}

下面演示一下:基类是封闭图形,派生类有三角形,四边形。

代码如下所示:

#include<iostream>
using namespace std;
class shape
{
public:virtual void show() = 0;
};class triangle :public shape
{
public:triangle(double a,double b,double c):a(a),b(b),c(c){}void show(){cout << "triangle" << endl;}
private:double a;double b;double c;};class quadrangle :public shape
{
public:quadrangle(double a,double b,double c,double d):a(a),b(b),c(c),d(d){}void show(){cout << "quardrangle" << endl;}
private:double a;double b;double c;double d;
};int main()
{shape *s=nullptr;triangle t(1, 2, 3);quadrangle q(1, 2, 3, 4);s = &t;s->show();s = &q;s->show();return 0;
}

抽象类

如果一个类至少有一个纯虚函数,那么就称该类为抽象类,因此上面那个shape类就是抽象类。

对于抽象类的使用规则:

1.因为抽象类 中至少包含一个没有定义功能的纯虚函数,抽象类只能作为其他类的基类的来使用,不能建立抽象类对象,只能为派生类提供一个接口规范,其功能由派生类给出。

2.不允许从具体类中派生出抽象类

3.抽象类不能用作参数类型,函数返回值类型或者显示转换类型

4.可以声明抽象类类型的指针和引用,此指针可以指向它的派生类对象进而实现动态多态性

5.如果这个派生类没有重写虚函数,那么这个 派生类就是简单继承这个纯虚函数,那么这个派生类就是一个抽象类

6.在抽象类中可以定义普通成员函数或者虚函数

注意函数体为空的虚函数不是纯虚函数,函数体为空不代表没有函数体,纯虚函数没有函数体

override

如果一个成员函数是虚函数,那么在后续派生类里的同名函数都是虚函数,无须再用virtual修饰。这样就会出现以下问题:

1.这样在函数很多的情况下,就难以分辨哪些函数是派生类特有的成员函数,哪些函数继承自基类;

2.还有可能派生类可能无意使用了一个同名但函数原型不同的函数”覆盖“了基类的虚函数

#include<iostream>
using namespace std;
class base
{
public:virtual void f() = 0;//纯虚函数virtual void g()const//虚函数{cout << "base:g()" << endl;}void h()//一般成员函数{cout << "base:h()" << endl;}
};class derived :public base
{
public:void f()//纯虚函数重写{cout << "derived:f()" << endl;}void g()//不是虚函数重新,遗漏了const修饰{cout << "derived:g()" << endl;}void h()//一般成员函数{cout << "derived:h()" << endl;}
};int main()
{base* b = nullptr;derived c;b = &c;b->f();b->g();b->h();return 0;
}

C++11增加了一个特殊的标识符override,它可以显示地标记虚函数重写 ,明确代码编写者的意图:派生类成员函数名后面有override修饰,那么这个函数就一定是虚函数,而且函数原型也必须与基类声明一致,否则编译错误。

void f()override//纯虚函数重写
{cout << "derived:f()" << endl;
}

final

final可以在类名后面使用,显式的禁止类被继承,不能再有派生类

final可以在虚函数后面使用,显式的禁止该函数在派生类中再次被重写

例如

#include<iostream>
using namespace std;class base
{
public:virtual void f() = 0;//纯虚函数virtual void g()//虚函数{cout << "base:g()" << endl;}
};class derived :public base
{
public:void f()override final//纯虚函数重写,并不允许被重写{cout << "derived:f()" << endl;}void g()override//虚函数重写{cout << "derived:g()" << endl;}};class last final :public derived//表示last不允许被继承,last也不会再有派生类
{/*void f()override //纯虚函数重写,并不允许被重写{cout << "last:f()" << endl;}*/void g()//虚函数重写{cout << "last:g()" << endl;//可以重写}
};

 

last类在类名后使用了final,使它变成了类体系的终点

在derived类的函数f后使用了final,表示在后面的派生类中禁止重写该虚函数。

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

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

相关文章

【十大排序算法】----C语言版插入排序(详细图解)

目录 一&#xff1a;插入排序——原理 二&#xff1a;插入排序——分析 三&#xff1a;插入排序——实现 四&#xff1a;插入排序——效率 一&#xff1a;插入排序——原理 插入排序的原理和基本思想&#xff1a;把待排序的记录按其关键码值的大小逐个插入到一个已经排好序…

Django使用

一、根目录下安装 pip install django 二、创建djiango项目 django-admin startproject 项目名称 三、创建app python manage.py startapp app名称 四、启动 python manage.py runserver 五、编写URL与视图关系&#xff0c;相对路径 1、manage.py&#xff08;见资源绑定…

多元化、高辨识显示丨基于G32A1445的汽车尾灯解决方案

由刹车灯、倒车灯、转向灯、雾灯等组成的汽车尾灯&#xff0c;既能在光线低暗时发出照明信息&#xff0c;也可向周围环境传递车辆的行驶状态与意图信号&#xff0c;对于行车安全起着至关重要的作用。与传统尾灯相比&#xff0c;贯穿式汽车尾灯更加醒目、美观、安全&#xff0c;…

CSS2(一):CSS选择器

文章目录 1、CSS基础1.1 CSS简介1.2 CSS编写位置1.2.1 行内样式1.2.2 内部样式1.2.3 外部样式1.2.4 样式优先级 1.2.5 CSS代码风格 2、CSS选择器2.1、基本选择器2.1.1 通配选择器2.1.2 元素选择器2.1.3 类选择器2.1.4 ID选择器2.1.5 总结 2.2、CSS复合选择器2.2.1 交集选择器2.…

海外媒体宣发:新加坡.马来西亚如何在海外媒体投放新闻通稿-大舍传媒

导言 随着全球化的进程加速&#xff0c;海外市场对于企业的发展越来越重要。而在海外媒体上宣传企业的新闻通稿&#xff0c;成为了拓展海外市场和提升企业知名度的重要手段之一。本文将介绍大舍传媒对于如何在海外媒体上投放新闻通稿的经验和策略。 准备工作&#xff1a;了解…

Hive 特殊的数据类型 Array、Map、Struct

Array 数组类型&#xff0c;存储数据类型一致的列表数据。 我们可以使用 array 方法来创建一个数组&#xff0c;如下所示&#xff1a; select array(1,2,3,4,5);如果其中的数据类型不一致&#xff0c;那么它会转换成统一的数据类型&#xff08;前提是能够进行转换&#xff0…

力扣HOT100 - 322. 零钱兑换

解题思路&#xff1a; 动态规划 class Solution {public int coinChange(int[] coins, int amount) {int[] dp new int[amount 1];Arrays.fill(dp, amount 1);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j) {if (coins[j] < i) …

宠物管理系统带万字文档

文章目录 宠物管理系统一、项目演示二、项目介绍三、19000字论文参考四、部分功能截图五、部分代码展示六、底部获取项目源码和万字论文参考&#xff08;9.9&#xffe5;带走&#xff09; 宠物管理系统 一、项目演示 宠物管理系统 二、项目介绍 基于springbootvue的前后端分离…

新串口通道打通纪实

在计算机系统中&#xff0c;串口是“古老”的通信方式&#xff0c;和它同时代的“并口”通信方式已经消失了。但它仍然顽强的存活着&#xff0c;主要原因是在开发和调试底层软件时还经常用到串口。 正因为有这样的需求&#xff0c;幽兰代码本是支持串口的&#xff0c;而且有两种…

【现代C++】概念的使用

现代C&#xff08;特别是C20及以后的版本&#xff09;引入了概念&#xff08;Concepts&#xff09;&#xff0c;这是一种指定模板参数必须满足的约束的方式。概念使得模板代码更清晰&#xff0c;更容易理解和使用&#xff0c;并且能在编译时提供更好的错误信息。以下是C概念的关…

UStaticMesh几何数据相关(UE5.2)

UStaticMesh相关类图 UStaticMesh的数据构成 UStaticMesh的FStaticMeshSourceModel UStaticMesh的Mesh几何元数据来自于FStaticMeshSourceModel&#xff0c; 一级Lod就存在一个FStaticMeshSourceModel. FStaticMeshSourceModel几何数据大致包含以下几类: Vertex(点), VertexI…

玩转Matlab-Simscape(初级)- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(理论部分2)

** 玩转Matlab-Simscape&#xff08;初级&#xff09;- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&#xff08;理论部分2&#xff09; ** 目录 玩转Matlab-Simscape&#xff08;初级&#xff09;- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&am…

风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)完整代码风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码) 完整代码 clc; clear close allX = xlsread(风电场预测.xlsx)

python数据分析——seaborn绘图2

参考资料&#xff1a;活用pandas库 # 导入库 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns tipspd.read_csv(r"...\seaborn常用数据案例\tips.csv") print(tips.head()) 1、成对关系表示 当数据大部分是数据时&#xff0c;可以使用…

分享一个基于Qt的Ymodem的上位机(GitHub开源)

文章目录 1.项目地址2.Ymodem 协议介绍3.文件传输过程4.使用5.SecureCRT 软件也支持Ymodem6.基于PyQt5的Ymodem界面实现案例 1.项目地址 https://github.com/XinLiGH/SerialPortYmodem 基于VS2019 Qt5.15.2 编译&#xff0c;Linux下编译也可以&#xff0c;这里不做说明。 2.…

Python | Leetcode Python题解之第89题格雷编码

题目&#xff1a; 题解&#xff1a; class Solution:def grayCode(self, n: int) -> List[int]:ans [0] * (1 << n)for i in range(1 << n):ans[i] (i >> 1) ^ ireturn ans

如何在云电脑实现虚拟应用—数据分层(应用分层)技术简介

如何在云电脑实现虚拟应用—数据分层&#xff08;应用分层&#xff09;技术简介 近几年虚拟化市场实现了非常大的发展&#xff0c;桌面虚拟化在企业中应用越来越广泛&#xff0c;其拥有的如下优点得到大量企业的青睐&#xff1a; 数据安全不落地。在虚拟化环境下面数据保存在…

STL库简介

一、STL库的概念 STL&#xff1a;是C标准库的重要追组成部分&#xff0c;不仅是一个可以复用的组件库&#xff0c;而且还是一个包含了数据结构和算法的软件框架。 二、STL的版本 原始版本 Alexander Stepanov、 Meng Lee 在惠普实验室完成的原始版本&#xff0c; 是一个开源…

JVM 双亲委派机制详解

文章目录 1. 双亲委派机制2. 证明3. 优势与劣势 1. 双亲委派机制 类加载器用来把类加载到 Java 虚拟机中。从JDK1.2版本开始&#xff0c;类的加载过程采用双亲委派机制&#xff0c;这种机制能更好地保证 Java 平台的安全。 1.定义 如果一个类加载器在接到加载类的请求时&…