你明白C++中的多态吗?(暑假提升-多态专题)

内不欺己,外不欺人。———孔子


有趣的多态

  • 1、前言
  • 2、概念
  • 3、多态定义与产生条件
  • 4、多态的重要组成成员-(虚函数)
  • 5、虚函数的重写(覆盖)
  • 6、辅助关键字override与final(了解即可)
  • 7、重载,重定义(隐藏),重写(覆盖)
  • 8、抽象类
  • 9、多态的原理
    • 9、1、虚函数表
    • 9、2、多态原理

1、前言

在最开始,我会讲明白分那么多的小标题的目的就是方便不懂多态的人能够有大概的框架,知道多态的能够有目的的去复习。所以标题分那么多请不要见怪。多多包涵。
在这篇文章中已经讲过了C++中的一个重要的特性-继承,想回顾一下的可以点击一下链接,复习复习。接下来我们将进行多态的讲解,其中也有一部分内容和继承比较相似,容易搞混,所以我尽力的讲清楚多态的特点和注意点,如果是继承的问题想不明白的话,可以看看我之前的文章,其中也算是讲的比较详细的。

2、概念

多态,也可以理解是多种状态。不同的状态完成不同的事情,可能是目的一样,但是不同的对象,实现的结果却是不同的。
意思是类产生的对象(存在继承的关系),在实现函数的时候,调用的是同一个函数名,但是执行出来的结果却是大相径庭的。

3、多态定义与产生条件

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。
比如:Student继承了 Person。Person对象买票全价,Student对象买票半价。
除此之外,想要实现多态还需要两个条件。
1. 必须通过基类的指针或者引用调用虚函数
2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

在这里插入图片描述

重写与继承中的隐蔽有区别或者说是重定义是不一样的!
在继承中,函数的重定义只需要函数名字相同就能够构成重定义,但是对于多态的实现必须要三个要素都相同函数名,参数,返回值
其中不管是基类还是派生类,在进行多态函数调用的时候,必须是用基类的引用或者是指针。

4、多态的重要组成成员-(虚函数)

和虚继承相似,虚函数的定义也会用到virtual关键字,但是关键字的位置是不一样的,怎么说呢,就好像是&的操作一样,在不同的场景之下,可能是取地址也有可能是引用,所以要注意区别,分别看待。在这里插入图片描述

5、虚函数的重写(覆盖)

虚函数的重写就是在子类继承之后在其中有一个和父类三要素都相同的虚函数,称子类的虚函数重写了基类的虚函数。
注意: 在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范,不建议这样使用。

class Person 
{
public:
	virtual void BuyTicket() { cout << "买票-全价" << endl; } 
};
class Student : public Person 
{
public:
	virtual void BuyTicket() { cout << "买票-半价" << endl; 
}

析构函数的重写,与众不同。析构函数即使不加virtual关键字也会重写,当然了,即使是名字不同也还是会重写。名字的不同是在我们编辑的时候定义的不同的名字,但是对于编译器来说,到编译的那一步的时候,已经将所有的析构函数统一名字了。编译后析构函数的名称统一处理成destructor

6、辅助关键字override与final(了解即可)

override与final关键字能够很好的帮助我们检查多态中函数重写可能存在的问题。
**override:**检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。
final: 修饰虚函数,表示该虚函数不能再被重写

7、重载,重定义(隐藏),重写(覆盖)

三种概念实现的东西,相对而言是类似的,能够概括的认为,表面上是为了调用相同的东西,但是细微的区别能够又有着不同的处理方法,可能还会是不同的效果。
所以三种不同的操作,定义之间对于区别的掌握也是十分重要的

在这里插入图片描述

8、抽象类

抽象类的形成就是在虚函数的最后加上“=0”,抽象类不能够实例化,如果继承的话,形成的派生类如果不重写虚函数也不能够实例化对象。所以抽象类的出现,一定程度上要求严格了虚函数重写,因为不重写就不能实例化出对象,也就没有下面之后的事情。同时抽象类也称为纯虚函数(我个人看到这个名词就感觉像是不能产生对象的意思)。

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

class Benz :public Car
{
public:
    virtual void Drive()
 {
	cout << "Benz-舒适" << endl; 
 }
};

另外,纯虚函数体现了接口的继承观念。

9、多态的原理

9、1、虚函数表

就像是在继承中的虚继承一样,其中作为基类的A在内存中存放的位置是在最底下,但是同样的,为了保证是相同的a,B和C中在内存中的第一个地址的位置存放着虚基表来帮助找到a的位置,能够修改和得到a的值。这篇文章中还有图的解释,这里就不再多赘述了。
**有趣的是,多态中的原理和虚继承好像还有点相似,**其中多态中,有着另一种表虚函数表。为了更能够理解虚函数表的作用,我们先从一个题目来入手。

// 这里常考一道笔试题:sizeof(Base)是多少? 
class Base
{
public:
    virtual void Func1()
    {
        cout << "Func1()" << endl;
    }
private:
    int _b = 1;
};

答案是8byte而不是只有4个byte,那么多出来的4byte是什么?那其实是一个指针,一个虚函数表指针。当然了,如果一个基类中有多个虚函数的话,只会存在一个虚函数表指针,也就是意味着在刚刚的Base类中,即使还有别的虚函数,最后Base的大小也还是4byte。虚函数表指针简称也叫做虚表指针。
但是,如果是多继承下来的子类中的虚函数表可能不止一个。
在这里插入图片描述
编译器,实现多态的方法是靠在第一个元素位置的地址指向的地址,调用不同的函数。
满足多态的条件:那么这里的调用生成的指令,就会去指向对象中的虚表中找对应的函数进行调用。
不满足多态的条件:直接就确定函数的地址,而不去虚函数表里面找,因为直接找到了。
为什么重写也称为是覆盖呢?因为在地层中,重写条件满足后,当前对象中的虚函数表就会改写,原本从父类继承下来的相同的虚函数就会换成子类中的函数指针的位置,这样的步骤看做为覆盖是十分合理的。

9、2、多态原理

了解了虚函数表之后,想一想在第三个标题中图片的内容,其实在底层的实现中也就是像这个样子的。在这里插入图片描述
**虚表:**虚函数表,存的虚函数,目标实现多态。
**虚基表:**存的是当前位置距离虚基类部分的位置的偏移量,防止存在菱形继承的二异性问题。
Tip: 每一个存在的数据都会存放在计算机内部,而计算机拥有着。栈,堆,静态区,常量区。那么对于虚表来说,存放在哪呢?在这里插入图片描述
由此可见,vs上的虚表是存在于常量区之中的。

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

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

相关文章

微信定时推送LeetCode每日一题,再也不怕没人喊你刷题了

前段时间发过一篇关于微信机器人开发的文章&#xff0c;讲述了如何快速开发一个微信机器人&#xff0c;本篇文章就来实现一个最近开发的一个功能案例&#xff0c;在这个案例中会遇到了各种问题&#xff0c;可以帮助大家减少自己去踩坑的时间。通过此案例也可以帮助你去扩想一些…

HarmonyOS Next应用开发之系统概述

一、鸿蒙系统概述 鸿蒙系统可以分为华为鸿蒙系统&#xff08;HUAWEI HarmonyOS&#xff09;和开源鸿蒙系统&#xff08;OpenHarmony&#xff09;&#xff0c;华为鸿蒙系统是基于OpenHarmony基础之上开发的商业版操作系统。他们二者的关系可以用下图来表示&#xff1a; 1.1、…

Python 轻松生成多种条形码、二维码 (Code 128、EAN-13、QR code等)

条形码和二维码是现代信息交换和数据存储的重要工具&#xff0c;它们将信息以图形的形式编码&#xff0c;便于机器识别和数据处理&#xff0c;被广泛应用于物流、零售、医疗、教育等各领域。 本文将介绍如何使用Python快速生成各种常见的条形码如Code 128、EAN-13&#xff0c;…

CentOS7 安装 git 命令

通过yum源install下载的git版本比较低&#xff0c;不推荐此方式安装。 官网下载最新版git源码&#xff1a;Git 1. 解压安装包 tar -xzvf git-2.45.2.tar.gz 2. 安装相关依赖 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils…

如何用Vue3和Plotly.js创建交互式表格?

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Plotly.js 动态生成 HTML 表格 应用场景介绍 在数据分析和可视化领域&#xff0c;经常需要以表格的形式展示数据。Plotly.js 是一款功能强大的 JavaScript 库&#xff0c;不仅可以创建交互式图表&#xff0c;…

【源码+文档+调试讲解】文物管理系统

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

前端与嵌入式开发通信之QWebChannel(Qt)

前端与嵌入式开发通信之QWebChannel 最近开发中需要用到和c开发的操作台进行通信的的需求&#xff0c;就找到了这个技术&#xff0c;记录一下 首先需要安装导入 qwebchannel npm i qwebchannel import { QWebChannel } from "qwebchannel"; 初始化qwebchannel并封…

嵌入式音频处理技术的现在发展及未来的方向

嵌入式音频处理技术&#xff1a;从音频流媒体到声音识别 嵌入式音频处理技术的迅猛发展正在改变我们的生活方式&#xff0c;从音频流媒体到声音识别&#xff0c;这个领域为人们的生活和工作带来了巨大的影响。本文将探讨嵌入式音频处理技术的最新趋势和应用&#xff0c;以及提…

安防管理平台LntonCVS视频汇聚融合云平台智慧火电厂安全生产管理应用方案

中国的电力产业作为国民经济发展的重要能源支柱&#xff0c;被视为国民经济的基础产业之一。目前&#xff0c;我国主要依赖火力发电&#xff0c;主要燃料包括煤炭、石油和天然气等&#xff0c;通过燃烧转化为动能&#xff0c;再转变为电能输送至全国各地。火力发电量占全国发电…

告别混乱,可道云企业网盘个人标签,让文件管理更轻松

在信息爆炸的时代&#xff0c;你是不是常常觉得自己的大脑就像一台过载的处理器&#xff0c;各种文件、资料、想法在脑海中“打架”&#xff0c;让你焦头烂额&#xff1f; 别担心&#xff0c;可道云企业网盘个人标签功能来拯救你的“大脑内存”了&#xff01; 我们需要告别无…

tensorflow之欠拟合与过拟合,正则化缓解

过拟合泛化性弱 欠拟合解决方法&#xff1a; 增加输入特征项 增加网络参数 减少正则化参数 过拟合的解决方法&#xff1a; 数据清洗 增大训练集 采用正则化 增大正则化参数 正则化缓解过拟合 正则化在损失函数中引入模型复杂度指标&#xff0c;利用给w增加权重&#xff0c;…

如何分析软件测试中发现的Bug!

假如你是一名软件测试工程师&#xff0c;每天面对的就是那些“刁钻”的Bug&#xff0c;它们像是隐藏在黑暗中的敌人&#xff0c;时不时跳出来给你一个“惊喜”。那么&#xff0c;如何才能有效地分析和处理这些Bug&#xff0c;让你的测试工作变得高效且有趣呢&#xff1f;今天我…

AWS-WAF-Log S3存放,通过Athena查看

1.创建好waf-cdn 并且设置好规则和log存储方式为s3 2. Amazon Athena 服务 使用 &#xff08;注意s3桶位置相同得区域&#xff09; https://docs.aws.amazon.com/zh_cn/athena/latest/ug/waf-logs.html#waf-example-count-matched-ip-addresses 官方文档参考,建一个分区查询表…

内容协商源码解析与自定义 MessageConverter

目录 内容协商 1、引入xml依赖 2、postman分别测试返回json和xml 3、开启浏览器参数方式内容协商功能 4、内容协商原理 5、自定义 MessageConverter 综上 内容协商 根据客户端接收能力不同&#xff0c;返回不同媒体类型的数据。 若客户端无法解析服务端返回的内容&#…

SAP SD销售订单的ATP检查简介

前面的文章中我们解释了PP模块中的ATP检查,也解释了MM模块中的ATP的检查,本文将说明一下SD模块中的ATP检查。 SAP 销售ATP(可用性检查)详解 ATP(Available-to-Promise)检查是SAP中的一项关键功能,用于确保在创建销售订单时能够满足客户需求。本文将详细介绍SAP销售ATP检…

【人工智能】-- 搜索技术(状态空间法)

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;引言 &#x1f348;介绍 &#x1f349;状态空间法 &#x1f348;状态空间的构成 &#x1f34d;状态 &#x1f34d;算符…

一文带你快速了解项目ASPICE评估的那些事-MUNIK

01、摘要 随着汽车电动化、智能化和互联化不断演进&#xff0c;汽车的电子电气架构得到持续升级&#xff0c;而汽车硬件方面逐渐趋向标准化。与此同时&#xff0c;汽车软件呈现出不断多样化和日益复杂的趋势。在这个大背景下&#xff0c;传统的软件开发流程已经无法满足这一需…

第4章 课程发布:模块需求分析,课程预览(模板引擎 静态页面),课程审核,课程发布(分布式事务,页面静态化:熔断降级),课程搜索(es索引)

1 模块需求分析 1.1 模块介绍 课程信息编辑完毕即可发布课程&#xff0c;发布课程相当于一个确认操作&#xff0c;课程发布后学习者在网站可以搜索到课程&#xff0c;然后查看课程的详细信息&#xff0c;进一步选课、支付、在线学习。 下边是课程编辑与发布的整体流程&#…

C++ 编译体系入门指北

前言 之从入坑C之后&#xff0c;项目中的编译构建就经常跟CMake打交道&#xff0c;但对它缺乏系统的了解&#xff0c;遇到问题又陷入盲人摸象。对C的编译体系是如何发展的&#xff0c;为什么要用CMake&#xff0c;它的运作原理是如何的比较感兴趣&#xff0c;所以就想系统学习…

2008年上半年软件设计师【上午题】真题及答案

文章目录 2008年上半年软件设计师上午题--真题2008年上半年软件设计师上午题--答案 2008年上半年软件设计师上午题–真题 2008年上半年软件设计师上午题–答案