C++多态_C++回顾

news2024/11/19 16:42:50

多态的概念

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

什么是多态

静态的多态

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

动态的多态

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

父子类:

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

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

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

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

析构函数建议是虚函数

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

A* ptr=new B;
delete ptr;

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

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

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

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

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

纯虚函数

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

抽象类

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

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

接口继承和实现继承

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

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

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

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

override和final

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

final

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

override

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

多态的原理

虚函数表

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

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

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

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

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

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

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

经典题目 

参见资料。

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

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

相关文章

【Java网络编程05】网络原理进阶(三)

1. HTTP协议概述 HTTP协议:又被称为"超文本传输协议",是一种使用非常广泛的应用层协议,我们之前在文件章节介绍过文本文件与二进制文件的区别,文本可以看做字符串(能在utf8/gbk等编码表中查找到合法字符&am…

Unity类银河恶魔城学习记录1-14 AttackDirection源代码 P41

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili PlayerPrimaryAttackState.cs using System.Collections; using System.Co…

测试开发体系

软件测试 通过手工或者工具对 “被测对象”进行测试验证实际结果与预期结果之间是否存在差异 软件测试作用 通过测试工作可以发现并修复软件当中存在的缺陷,从而提高用户对产品的使用信心测试可以降低同类型产品开发遇到问题的风险 软件缺陷 软件缺陷被测试工程…

京东数据分析(电商数据查询):2023年冲锋衣行业大卖,销售额同比增长96%!

在服装行业,每年都会出现不同的服装爆款,成为人们时尚穿搭的新宠,2023年的服装爆款无疑是冲锋衣。 在社交平台上,冲锋衣鲨鱼裤运动鞋的搭配一时间成为许多女性消费者的户外潮流穿搭,不少网友点赞表示“很出片”。对于…

python创建pdf文件

目录 一:使用reportlab库 二:使用使pdf库 在Python中生成PDF文件可以使用多种库,其中最常用的是reportlab和fpdf。以下是使用这两个库生成PDF文件的示例代码: 一:使用reportlab库 1:写入文字信息 from r…

34 使用 LNMP 架构部署动态网站环境

源码包程序 LNMP 动态网站部署架构 LNMP 动态网站部署架构是一套由 Linux Nginx MySQL PHP 组成的动态网站系统 解决方案。 1. 准备工作 在使用源码包安装服务程序之前,首先要让安装主机具备编译程序源码的环境。这需要 具备 C 语言、C语言、Perl 语言的编译器&…

宝塔+php+ssh+vscode+虚拟机 远程调试

远程(虚拟机)宝塔 安装扩展 配置文件添加,zend_extension看你虚拟机的具体位置 [Xdebug] zend_extension/www/server/php/74/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so xdebug.modedebug xdebug.start_with_requesttrigger xdebug.client_host&quo…

关于RabbitMQ面试题汇总

什么是消息队列?消息队列有什么用? 消息队列是一种在应用程序之间传递消息的通信机制。它是一种典型的生产者-消费者模型,其中生产者负责生成消息并将其发送到队列中,而消费者则从队列中获取消息并进行处理。消息队列的主要目的是…

spring boot学习第十篇:elastic search必须使用用户名密码授权后才能访问、在java代码中操作索引

前提条件:安装好了elastic search服务,参考:elastic search入门_ubuntu elasticsearch 密码-CSDN博客 1、配置elastic search必须使用用户名密码授权才能访问 1.1开启x-pack验证 修改config目录下面的elasticsearch.yml文件,添…

#Z2322. 买保险

一.题目 二.思路 1.暴力 训练的时候&#xff0c;初看这道题&#xff0c;这不就打个暴力吗&#xff1f; 2.暴力代码 #include<bits/stdc.h> #define int long long using namespace std; int n,m,fa,x,y,vis[1000001],ans; vector<int> vec[1000001]; void dfs(i…

LabVIEW高精度微小电容测量

LabVIEW高精度微小电容测量 在电子工程和科研领域&#xff0c;精确测量微小电容值是一项有一定要求的任务&#xff0c;尤其在涉及到高精度和低成本时。设计了一种基于LabVIEW高精度微小电容测量系统&#xff0c;旨在提供一个既经济又高效的解决方案。 该系统的核心在于使用FD…

Vue3.0(三):Vue组件化深入理解

Vue组件化深入理解 生命周期 每个组件都可能经历 创建、挂载、更新、卸载等一系列过程 在每个阶段&#xff0c;我们可能会添加一些属于自己的逻辑代码 在Vue中&#xff0c;生命周期通过生命周期函数实现 生命周期函数实际上就是回调函数&#xff0c;在某个时间会被Vue源码调…

14.scala隐式转换

目录 概述实践代码执行结果 结束 概述 隐式转换&#xff1a;偷偷的(隐式)对现有功能进行增强(转换) 实践 代码 package com.fun.scalaimport java.io.File import scala.io.Sourceobject ImplicitApp {def main(args: Array[String]): Unit {// implicit 2 to 等价 &…

后台系统--搭建前端环境

这里写目录标题 1. 安装vscode1.1 安装1.2 安装插件 2. 安装node.js&#xff0c;推荐163. 创建工作区3.1 创建空文件夹&#xff0c;不能有中文3.2 vscode打开文件夹&#xff0c;保存为工作区3.3 安装依赖 1. 安装vscode 1.1 安装 1.2 安装插件 2. 安装node.js&#xff0c;推荐…

C语言之数据在内存中的存储

目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断什么是大小端&#xff1f;为什么有大小端&#xff1f;练习1练习2练习3练习4练习5练习6 3. 浮点数在内存中的存储浮点数存的过程浮点数取得过程练习题解析 1. 整数在内存中的存储 在讲解操作符的时候&#xff0c;我们已经…

Windows下Node.js下载安装及环境变量配置教程

Windows下Node.js下载安装及环境变量配置教程 安装版本&#xff1a;node-v18.19.0-x64.msi 文章目录 Windows下Node.js下载安装及环境变量配置教程一、Node.js和NPM简介二、下载地址三、安装步骤四、环境配置五、安装淘宝镜像总结 一、Node.js和NPM简介 1、Node.js &#xf…

嵌入式软件设计方式与方法

1、嵌入式软件与设计模式 思从深而行从简 软件开发&#xff0c;难的不是编写软件&#xff0c;而是编写功能正常的软件。软件工程化才能保证软件质量和项目进度&#xff0c;而设计模式使代码开发真正工程化&#xff0c;设计模式是软件工程的基石。 所谓设计模式就是对常见问题的…

[BUUCTF]-PWN:inndy_echo解析

查看保护 查看ida 有格式化字符串漏洞&#xff0c;可以修改printf的got表内地址为system&#xff0c;传参getshell 解法一&#xff1a; 在32位中可以使用fmtstr_payload直接修改&#xff0c;免去很多麻烦 完整exp&#xff1a; from pwn import* pprocess(./echo) premote(n…

《低功耗方法学》翻译——附录B:UPF命令语法

附录B&#xff1a;UPF命令语法 本章介绍了文本中引用的所选UPF命令的语法。 节选自“统一电源格式&#xff08;UPF&#xff09;标准&#xff0c;1.0版”&#xff0c;经该Accellera许可复制。版权所有&#xff1a;(c)2006-2007。Accellera不声明或代表摘录材料的准确性或内容&…

Could not connect to Redis at 127.0.0.1:6379:由于目标计算机积极拒绝,无法连接...问题解决方法之一

一、问题描述 将Redis压缩包解压后&#xff0c;安装Redis过程中出现问题Could not connect to Redis at 127.0.0.1:6379:由于目标计算机积极拒绝&#xff0c;无法连接... 官网windows下redis开机自启动的指令如下&#xff1a; 1、在redis目录下执行 redis-server --service-in…