C++多态_C++回顾

多态的概念

通俗的说多态就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的概念。

什么是多态

静态的多态

静态的多态即函数重载,编译时是参数匹配和函数名修饰规则。

动态的多态

运行时实现,跟指向对象有关。

父子类:

        虚函数即被virtual修饰的类成员函数。

        虚函数的重写:派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),也就是派生类的虚函数重写了基类的虚函数。

        在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然可以构成重写,因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性,但是这种写法不是很规范,不建议使用。

        虚函数重写的两个例外:①协变,即派生类重写基类虚函数时,与基类虚函数的返回值类型不同;基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用成为协变。②析构函数的重写,如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否加virtual关键字,都与基类的析构函数构成重写,虽然基类与派生类析构函数名字不同。看起来违背了重写规则,其实不然,可以理解为编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor。

析构函数建议是虚函数

为什么析构函数建议是虚函数?

A* ptr=new B;
delete ptr;

当通过基类指针或引用来操作派生类对象时,如果析构函数不是虚函数,那么在删除基类指针时,只会调用基类的析构函数,而不会自动调用派生类的析构函数。这将导致派生类的部分资源无法正确释放,可能会引发内存泄漏或其他资源泄露问题。

如果析构函数是虚函数,那么在删除一个指向派生类对象的基类指针时,将会根据对象的实际类型调用相应的析构函数,确保正确地清理资源。

如果析构函数不是虚函数,那么在删除一个派生类对象时,可能会导致派生类中特有的资源(如动态分配的内存、打开的文件句柄等)没有被正确释放,从而引发资源泄漏。

可以提高代码的健壮性和可维护性。

总的来说,如果一个类设计为可以被继承,通常建议将析构函数声明为虚函数,以确保在多态的情况下能够正确地释放资源和执行清理操作。

纯虚函数

在虚函数的后面写上=0,则这个函数为纯虚函数。

抽象类

包含纯虚函数的类叫做抽象类,也叫接口类。

抽象类不能实例化出对象,派生类继承后也不能实例化出对象,只有重写虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

接口继承和实现继承

普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。

虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。

所以如果不实现多态,不要把函数定义成虚函数。

重载、覆盖(重写)、隐藏(重定义)的对比

override和final

C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重载,但是这种错误在编译期间是不会报出的,只有在程序运行时,没有得到预期结果的情况下由程序员debug才能得到修复。基于此,C++11提供了override和final两个关键字,来帮助用户检测是否构成重写。

final

修饰虚函数,表示该虚函数不能再被重写。

override

检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。

多态的原理

虚函数表

一个类中如果有虚函数存在,那么在对象中,会存在一个指针,叫做虚函数表指针。一个含有虚函数的类中都至少有一个虚函数表指针。因为虚函数的地址要被放到虚函数表中。虚函数表也叫虚表。

虚函数表不仅存在于含有虚函数的对象中,同时也存在于它的派生类对象中。

如果派生类对虚函数重写,那么基类对象虚表和派生类对象虚表是不一样的。派生类对象存在的虚表是重写的虚函数,覆盖就是指虚表中虚函数的覆盖。重写是语法层面的说法,覆盖是原理层面的说法。

只有虚函数才会在被继承后放入虚表。

虚函数表本质是一个存虚函数指针的指针数组,一般情况下这个数组最后面放了一个nullptr。

派生类虚表生成过程:先将基类中的虚表内容拷贝一份到派生类虚表中;如果派生类重写了基类中某个虚函数,那就用派生类自己的虚函数覆盖虚表中基类的虚函数;派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。

虚函数存在哪?虚表存在哪?应注意虚表存的是虚函数指针,而不是虚函数。虚函数和普通的函数一样,都是存在代码段的,只是它的指针存到了虚表中。对象中存的不是虚表。而是虚表指针。在VS下,虚表是存在于代码段的。

经典题目 

参见资料。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(篇九)MySQL常用内置函数

目录 ⌛数学函数 ⌛字符串函数 ⌛聚合函数 ⌛日期函数 📐获取当前时间 📐获取时间的某些内容 📐​编辑 📐格式化函数 📏format类型: ⌛系统信息函数 ⌛类型转换函数 数学函数 字符串函数 聚合函…

《计算机网络简易速速上手小册》第6章:网络性能优化(2024 最新版)

文章目录 6.1 带宽管理与 QoS - 让你的网络不再拥堵6.1.1 基础知识6.1.2 重点案例:提高远程办公的视频会议质量实现步骤环境准备Python 脚本示例注意事项 6.1.3 拓展案例1:智能家居系统的网络优化实现思路Python 脚本示例 6.1.4 拓展案例2:提…

Go语言每日一练 ——链表篇(三)

传送门 牛客面试笔试必刷101题 ---------------- 链表中的节点每k个一组翻转 题目以及解析 题目 解题代码及解析 package main import _"fmt" import . "nc_tools" /** type ListNode struct{* Val int* Next *ListNode* }*//*** 代码中的类名、方…

矩阵的正定(positive definite)性质的作用

1. 定义 注意,本文中正定和半正定矩阵不要求是对称或Hermite的。 2. 性质 3. 作用 (1)Axb直接法求解 cholesky实对称正定矩阵求解复共轭对称正定矩阵求解LDL实对称非正定矩阵求解复共轭对称非正定矩阵求解复对称矩阵求解LU实非对称矩阵求解…

离线环境怎么下载python依赖包

公司内网环境无网络,运行自动化脚本需要安装python模块 1、脚本依赖包及其版本获取,记录在requirements.txt中 pipreqs ./script --encodingutf8 requirements.txt注意,这里是将./script 里的python模块自动扫描并写入到requirements.txt中…

QT学习日记 | 显示类控件

目录 前言 一、QLabel控件 1、属性介绍 2、实战演练 (1)文本格式属性 (2)图片属性 (3)对齐、换行、缩进、边距属性 (4)伙伴属性 二、QLCDNumber控件 1、属性介绍 2、实战…

图灵之旅--二叉树堆排序

目录 树型结构概念树的表示形式 二叉树概念特殊的二叉树二叉树性质二叉树的存储二叉树的遍历前中后序遍历 优先级队列(堆)概念 优先级队列的模拟实现堆的性质概念堆的存储方式堆的创建 堆常用接口介绍PriorityQueue的特性PriorityQueue常用接口介绍优先级队列的构造插入/删除/获…

闲聊电脑(5)装个 Windows(一)

​夜深人静,万籁俱寂,老郭趴在电脑桌上打盹,桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭:冰箱大哥,上次说到硬盘分区和格式化,弄完之后,就该装系统了吧? 冰箱&#x…

确定问卷调查样本量

目录 1. 问卷数据类型1.1 定性数据&定性分析1.2 定量数据&定量分析 2. 确定初始样本容量:2.1 公式:2.2 Z值2.3 p2.4 e2.5 举例 3.调整初始样本容量:3.1 公式:3.2 结论就是 小结: 1. 问卷数据类型…

消息中间件之RocketMQ源码分析(七)

并行消费和顺序消费 ConsumeMessageService是一个通用的消费服务接口,它包含两个实现类org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService和 org.apache.rocketmq.client.impl.consumer.ConsumeMessageOrderlyService,这两个…

学习并用好大模型

大模型是个好东西,学好并用好益处多多~ 1. 运用大模型服务我们的工作 运用大模型服务于工作,可以从以下几个方面着手: 知识管理与检索: 利用大模型强大的自然语言处理能力,建立企业内部的知识库系统。员工可以通过提问…

03-Java单例模式 ( Singleton Pattern )

单例模式 单例模式设计要点单例模式基础实现摘要实现范例 单例模式的几种实现方式1. 懒汉式,线程不安全2. 懒汉式,线程安全3. 饿汉式4. 双检锁/双重校验锁(DCL,即 double-checked locking)5. 登记式/静态内部类6. 枚举…

记录关于node接收并解析前端上传excel文件formData踩的坑

1.vue2使用插件formidable实现接收文件,首先接口不可以使用任何中间件,否则form.parse()方法不执行。 const express require(express) const multipart require(connect-multiparty); const testController require(../controller/testController)/…

【论文精读】多模态情感分析 —— VLP-MABSA

Vision-Language Pre-Training for Multimodal Aspect-Based Sentiment Analysis 本篇论文发表于ACL-2022 原文链接 https://arxiv.org/abs/2204.07955 源码 GitHub - NUSTM/VLP-MABSA 模态:图像文本 基于多模态方面的情感分析(MABSA)近年来越来越受到关注。然而&am…

【Power Automate】规避流程30天的运行时限(只针对审批流)

众所周知,Power Automate的流程最多只能运行30天,到点之后直接超时,如果我们有超时时间设置的比较长的审批就会很麻烦,可能我们把审批节点的超时时间都设置为25天,结果第一个审批人就把25天拉满了,那第二个…

SpringBoot实战第三天

今天主要完成了: 新增棋子分类 棋子分类列表 获取棋子分类详情 更新棋子分类 更新棋子分类和添加棋子分类_分组校验 新增棋子 新增棋子参数校验 棋子分类列表查询(条件分页) 先给出分类实体类 Data public class Category {private Integer id;//主键IDNot…

七月论文审稿GPT第2.5和第3版:分别微调GPT3.5、Llama2 13B以扩大对GPT4的优势

前言 自去年7月份我带队成立大模型项目团队以来,我司至今已有5个项目组,其中 第一个项目组的AIGC模特生成系统已经上线在七月官网第二项目组的论文审稿GPT则将在今年3 4月份对外上线发布第三项目组的RAG知识库问答第1版则在春节之前已就绪至于第四、第…

C语言-3

定义指针 /*指针的概念:1.为了方便访问内存中的内容,给每一个内存单元,进行编号,那么我们称这个编号为地址,也就是指针。2.指针也是一种数据类型,指针变量有自己的内存,里面存储的是地址,也就是…

Vue ElementUI中el-table表格嵌套样式问题

一、表格嵌套要求: 两个表格嵌套,当父表格有children数组时子表格才展示;子表格数据少于父表格展示字段,且对应固定操作列不同; 二、嵌套问题: 当使用el-table的typeexpand实现表格嵌套时,样…

hbuiderX打包为apk后无法停止录音的解决方案

同一个APP在hbuilder和hbuilderX打包&#xff0c;出现没有麦克风权限 - DCloud问答 第一步&#xff1a; 在manifest.json的“模块权限配置”中勾选以下权限&#xff1a; <uses-permission android:name"android.permission.MODIFY_AUDIO_SETTINGS" /> <use…