C++当中的多态(二)

news2024/11/10 15:38:53

  (三)final和override关键字

  在继承和多态当中我们还会很经常看到这两个关键字final和override。这两个关键字的作用其实很简单。

  final关键字字面意思上理解就是我们这个虚函数是最后一个虚函数,之后不能够被重写。所以我们以后想要定义一个虚函数只能够被有限次重写,之后就不允许其发挥重写功能的时候就可以添加上这个关键字。同时在继承当中我们同样使用。我们可以在类定义之后加上final,加上final关键字之后的类就是最后一个类,不允许之后再被继承。样例如下:

  我们会发现程序运行的结果跟我们想想中的一样,使用final修饰的虚函数跟类都只能作为最后一个类或者虚函数进行使用,不允许重写和继承。

  对于我们的override关键字来说,其仅在多态当中发挥作用。我们可以使用override进行修饰我们派生类当中的虚函数,经过override限定的虚函数会自动进行检查,如果继承的基类当中该函数没有被设置成为虚函数就会产生报错。

  对于没有经过override修饰的函数,我们系统会认为它不是一个虚函数。之后我们在预期的派生类当中对其进行重写操作也不会出现我们想要的多态的效果,并且系统也不会进行报错,需要我们自己进行错误的查找操作,会带来很多不必要的麻烦。

  这个时候我们就可以使用override关键字对我们的派生类进行限定。当我们在派生类当中对虚函数进行重写的时候编译器就会自动向前进行检查操作,如果我们之前的基类没有将我们重写的函数定义为虚函数就会直接产生报错,节省了我们查找结果不匹配的错误的时间。

  (四)重载,重写,重定义的区别与对比

  相信大家在刚开始遇到这三种概念的时候都会产生疑惑。重载,重写,重定义很像诶,那么这三者有什么区别呢?我们需要注意什么吗?

  1.函数的重载

  函数的重载实际上就是同名函数因为参数类型的不同进行指定的匹配的情况。对于函数名相同的函数来说,我们根据函数名修饰规则会将参数跟我们的函数名进行混合得到一个结合体。只要有一点不同就可以进行特定的区分操作,进而得到同名函数发挥不同作用的效果。在函数重载的时候需要我们注意:函数的重载强制要求函数名相同,但是参数不同。并且重载的函数一定要在同一个作用域当中才可以发挥作用。其实很好理解,在不同的作用域当中允许定义同名数据。相应的数据只会在相应的作用域当中发挥作用。

  ※重点:同一作用域,函数名相同,参数不同
  2.函数的重写(覆盖)

  函数的重写就是我们正在介绍的,在多态当中进行的操作。重写的函数我们要求首先其必须是虚函数,之后必须满足重写的要求,即三同(函数名相同,函数返回值相同,函数的参数类型必须相同)其中也可以根据特定的语法允许协变的存在。之后还必须要求我们使用基类的指针或引用进行访问我们重写的虚函数。满足以上几点就可以构成多态。函数的重写,要求我们重写的函数分别在基类和派生类的作用域当中。

  ※重点:分别在基类和派生类的作用域当中,要求三同(协变除外),要求重写的函数是虚函数。

  在这里需要着重强调一点:实际上重写函数的判定中三同的要求只跟函数的参数类型,返回值类型,函数名有关。跟我们其他数据没有关系,加入我们在重写的虚函数当中加上默认参数,即使我们基类当中虚函数的默认参数跟派生类当中的虚函数的默认参数不同也是允许存在的。

  经过重写的虚函数会自动进行组装,将我们原本的虚函数的头部拿出来,之后再将我们重写的虚函数的函数体拿出来最终形成一个新的函数。这句语法看起来很奇怪,我们了解即可。代码样例如下:

  实际原理就跟我们讲到的那样会将原有虚函数的头部跟新的重写的函数体进行拼接,那么我们的默认参数的值就应该是A类当中的11,而不是我们B类当中的22。这么来看一切运行都跟我们的预期完全符合。

  3.函数的重定义(隐藏)

  函数重定义的概念在我们的继承章节当中提到过。当我们的派生类存在跟我们基类函数名完全相同的函数的时候,就构成了函数的隐藏。对于函数隐藏来说我们并不要求参数类型一致,不管我们参数相不相同,只要函数分别在基类跟派生类当中,只要不满足我们重写的要求的同名函数都可以构成函数的隐藏。

  ※重点:分别在基类和派生类的作用域当中,不满足重写的所有同名函数都是重定义

  (五)多态的底层原理

  之前我们介绍的都是多态的基本的使用方法。比如要求是虚函数,要求构成我们函数的重写,要求我们使用基类的指针或引用进行访问重写的虚函数的等等。但是函数具体是怎么进行实现的呢?这就涉及到了我们多态的底层原理了。

  实际上在我们的系统当中,当我们将基类当中的一个函数设置成为虚函数的时候,编译器会自动为这个类生成一张虚函数表,专门用来存储其中的虚函数所存放的地址。当我们的派生类在继承基类之后,这张虚函数表也会同时被继承下来。

  当我们在派生类当中对基类当中的虚函数进行重写操作的时候,就会有一个新的函数地址产生。我们将这个新的函数地址,这个新的函数地址就会指向派生类当中已经重写的虚函数。

  之后我们将这个地址放到继承下来的虚函数表当中原本虚函数的位置上就产生了一张新的虚函数表。对于这张新的虚函数表进行访问就只能访问到我们重写的虚函数,进而实现我们的多态了。

  我们通过调试窗口观察我们函数重写的过程:

  我们在基类当中创建两个虚函数,但是只对其中一个虚函数进行重写操作,另一个虚函数进行我们的对照。根据我们之前的分析来说,预期得到的结果应该是没有经过重写的虚函数的地址会保持不变直接复制下来,经过重写的虚函数的地址在虚函数表当中被新的函数覆盖而产生改变。我们会发现一切跟我们的预期完全吻合。

  实际上我们在派生类当中还可以重新向虚表当中添加虚函数,使得我们之后的类在继承的时候可以继续进行重写操作。在之后的类当中新添加的虚函数会自动添加到我们的虚函数表当中进行存储。我们进行观察:

  这个新添加的虚函数在我们的监视窗口当中可能看不出来,但是我们可以通过调用内存窗口进行观察,输入我们的虚表地址之后就会发现,在虚表当中一次保存着我们基类当中创建的两个虚函数,并且在前两个虚函数之后添加了一个新的地址,我们猜测这个地址就可能是我们在派生类当中新添加的虚函数的地址。接下来我们进行验证操作。

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

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

相关文章

word文档的读入(7)

获取了标准答案和学生答案后,就可以计算每位同学的填空题分数啦。我们将分数累加到studentData字典里的scoreTwo键中。需要注意的是,使用这个键之前,必须先在第一个for循环里和第二个for循环外,对它进行初始化赋值为0,…

一文搞懂线程的生命周期以及状态

一. Java 线程生命周期概述 Java 中的线程生命周期主要分为以下五个状态: 新建状态(NEW):线程被创建但尚未启动。可运行状态(RUNNABLE):线程可以被操作系统调度执行。阻塞状态(BLO…

如何投放Spotify广告:费用与关键考量

Spotify在2008年上市时,市场上已经充斥着各种竞争对手的音乐服务。这款音乐流媒体应用不仅打破了预期,还在180个市场上吸引了超过602百万用户,其中包括2.36亿订阅用户。现如今,它是全球最受欢迎的音频流媒体订阅服务。 Spotify广…

MySQL分组查询(DQL)

先看一下我的表内容和数据,再做接下来的例子和讲解1.分组函数的基本用法 select 字段列表 from 表名 [WHERE 条件] group by 分组字段名 [HAVING 分组后的过滤条件] 2.先声明where和having的区别 1.执行时机不同:where是分组之前进行过滤,…

❤Node08-Express-jwt身份认证

❤Node08-Express-jwt身份认证 1、token基本概念​ Session认证的局限性​ Session 认证机制需要配合Cookie才能实现。由于 Cookie 默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现…

特征值特征向量

正交矩阵 施密特正交化,本质上是正交​编辑投影定理的应用

再次进阶 舞台王者 第八季完美童模全球赛荣耀大使【李暖希】赛场秀场超燃合集!

7月20-23日,2024第八季完美童模全球总决赛在青岛圆满落幕。在盛大的颁奖典礼上,一位才能出众的少女——李暖希,迎来了她舞台生涯的璀璨时刻。 荣耀大使——李暖希,以璀璨童星之姿,优雅地踏上完美童模盛宴的绚丽舞台&am…

Python爱心射线(完整代码)

目录 系列目录 写在前面​ 完整代码 下载代码 代码分析 写在后面 系列目录 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3

【工资计算 / 2】

题目 枚举 #include <bits/stdc.h> using namespace std; int T; int a[] {0,1500,4500,9000,35000,55000,80000,1000000}; int b[] {0,3,10,20,25,30,35,45}; int check(int x) {if(x < 3500) return x;x - 3500;int tax 0;for(int i 1; i < 8; i){if(x >…

【Spring Boot 整合 MyBatis 详细教程】

文章目录 Spring Boot 整合 MyBatis 详细教程简介环境准备项目搭建项目结构配置项目1. pom.xml 配置2. 数据源和 MyBatis 配置3. 启动类配置4. Mapper 接口和 XML 映射文件 测试总结 Spring Boot 整合 MyBatis 详细教程 简介 Spring Boot 与 MyBatis 的整合可以让你轻松地构建…

Unity射击游戏开发教程:(35)轰炸敌人

现在敌人和飞机已经慢慢地越来越有各自地地行为了,在本文中,我们将介绍如何创建一个具有以下行为的敌人: 飞机会来回弹跳。飞机将有 4 架无人机轰炸机围绕飞机旋转。无人机轰炸机会偶尔投下沿着屏幕传播的炸弹。如果炸弹击中玩家或在随机时间后就会爆炸。如果炸弹没有击中玩…

机器学习--逻辑回归

逻辑回归 前情提要&#xff1a;线性回归 关于分类 C l a s s i f i c a t i o n Classification Classification 在逻辑回归中&#xff0c;我们只讨论 y ∈ { 0 , 1 } y\in\{0, 1\} y∈{0,1} 的情况。其中 1 1 1 表示 p o s i t i v e c l a s s positive \; class posit…

无人机培训机构组装调试技术详解

一、基础知识学习 在进入无人机组装调试领域之前&#xff0c;扎实的基础知识是不可或缺的。学员需掌握以下内容&#xff1a; 1. 无人机基本原理&#xff1a;了解无人机的飞行原理&#xff0c;包括升力、推力、重力和阻力等基本物理概念&#xff0c;以及无人机的飞行控制系统&…

CSP-J 初中的数学知识要学完, CSP-S 肯定是要需高中的知识

学信奥赛好处很多&#xff0c;进则科技特长&#xff0c;退则数理化强。

【97】shell实现精确延时

#!/bin/bash#使用date精确延时的函数&#xff0c;参数是毫秒 function precise_sleep_ms() {local duration_ms$1# 将毫秒转换为秒local duration_sec$(echo "scale9; $duration_ms / 1000" | bc)duration_sec$(printf "%.3f" "$duration_sec")#…

JDBC API详解二

PreparedStatement 作用&#xff1a; 预编译SQL的执行&#xff0c;&#xff0c;预防SQL注入问题 SQL注入 通过操作输入来修改预先定义好的SQL语句&#xff0c;用以达到执行代码对服务器进行攻击的方法&#xff1b; SQL注入延时 需求&#xff0c;完成用户登录 select * fr…

04 奇偶分家

题目&#xff1a; 代码&#xff1a; #include<iostream> using namespace std; #include<stdlib.h> #include<stdio.h>int main() {int N;cin>>N;int jicount0,oucount0;for(int i0;i<N;i){int temp;cin>>temp;if(temp%20){oucount;}else if…

【python基础】简要wxPython

文章目录 wxPython程序主事件循环通俗解释在窗口中添加控件 wxPython程序 import wxapp wx.App() frm wx.Frame(None, title第一个wxPython程序, size(400, 300), pos(100, 100)) frm.Show() app.MainLoop()app.MainLoop() 让应用程序进入主事件循环中。事件循环是一种事件或…

计网简简单单复习一下

文章目录 基础体系结构(分层模型)为什么要分层?OSI 七层模型?每一层的作用?TCP/IP 四层模型是什么?每一层的作用是什么?五层体系结构以及对应的协议每一层常见协议有哪些?从输入 URL 到页面展示到底发生了什么?URI和URL的区别;forward和redirect的区别DNS作用是什么?D…

Find My外卖箱|苹果Find My技术与外卖箱结合,智能防丢,全球定位

外卖箱是外卖送餐时使用的具有保温广告功能的箱包&#xff0c;一般具有轻便易携&#xff0c;保温性好&#xff0c;耐用&#xff0c;安全&#xff0c;易固定在外送电动车上等特点。随着生活水平的提高和餐饮行业的飞跃&#xff0c;外卖作为餐饮行业一个新的利润增长点&#xff0…