当前位置: 首页 > news >正文

C++程序设计——多态:虚函数、抽象类、虚函数表

注:以下示例均是在VS2019环境下

一、多态的概念

        通俗来讲,多态就是多种形态,当不同的对象去完成某个行为时,会产生出不同的状态。即不同继承关系的类对象,去调用同一函数时,产生不同的行为。

        比如”叫“这个行为,不同的动物,发出的声音是不同的。

二、多态的定义及实现

1.多态的构成条件

(1)必须是在继承环境下。

(2)被调用的函数必须是虚函数,且派生类中必须对该虚函数进行重写。

(3)必须通过基类的指针或引用去调用虚函数。

2.虚函数

        被virtual修饰的类成员函数。

3.虚函数的重写

3.1虚函数的重写(覆盖)

        派生类中有一个跟基类中完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名、参数列表都完全相同),称为子类的虚函数重写了基类的虚函数。

注意:

(1) 在重写基类虚函数时,派生类的虚函数不加virtual关键字修饰时,也可以构成重写(因为基类的虚函数被继承下来了,在派生类中依旧保持虚函数属性),但是这种写法不太规范,不建议这样使用。

(2)基类和子类虚函数的访问权限可以不同,但是一般都会将基类的虚函数设置为public。

3.2虚函数重写的两个例外

(1)协变(基类与派生类虚函数返回值类型不同)

        派生类重写基类虚函数时,与基类虚函数的返回值类型不同。即基类虚函数返回基类对象的指针或引用,派生类虚函数返回派生类对象的指针或引用时,称为协变

注意:

        基类和派生类必须属于同一继承体系;基类的返回值和派生类的返回值必须属于同一继承体系。但是返回值和基类、派生类不一定属于同一继承体系。

(2)析构函数的重写(基类与派生类析构函数名不同)

        如果基类的析构函数为虚函数,此时派生类析构函数只要定义,无论是否使用virtual关键字修饰,都与基类析构函数构成重写,但是析构函数名不同。

        函数名不同,看起来似乎违背了重写的规则,单其实是编译器对析构函数名做了特殊处理,编译后析构函数名称统一处理成了destructor。

4.C++11——override和final

        在某些情况下,由于疏忽可能会导致函数名字不同而无法构成重写,而这种错误在编译期间是不会报错的,只有在程序运行时没有得到预期结果才通过调试寻找错误,代价较高。

        因此C++11提供了override和final两个关键字,可以帮助用户检测是否重写。

4.1override关键字

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

4.2final关键字

        只能修饰虚函数。

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

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

注意:

(1)重写和重定义必须在继承体系内。

(2)重写只能是成员函数,而且是重写基类的虚函数;重定义既可以是成员函数,也可以是成员变量。

三、抽象类

1.抽象类概念

(1)在虚函数后面加上=0,则该函数为纯虚函数。

(2)包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化对象。

(3)派生类继承抽象类后,也不能直接实例化对象,必须对基类所有纯虚函数进行重写后才能实例化对象,否则派生类也是抽象类。

(4)纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口的继承。

注意:纯虚函数可以不用写函数体,写了不影响但没有意义。

2.接口继承和实现继承

2.1实现继承

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

2.2接口继承

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

        所有若不需要实现多态,不要把成员函数定义为虚函数。

四、多态的原理

1.虚函数表

只要类中存在虚函数,对象大小就会多4个字节:

 

        该指针指向的是一段连续的空间,即虚函数表,里面存放的是虚函数入口地址,且顺序与定义顺序相同。

对象模型:

基类虚表:

(1)虚函数入口地址存放顺序与虚函数定义顺序相同。

(2)一个类的多个对象公用同一个虚表

2.虚函数与虚表存放位置

(1)虚函数和普通函数一样存放在代码段,虚表存放的是虚函数指针。

(2)对象中存放的是虚表指针,不是虚表。

(3)在vs环境下,虚表是存放在代码段的。

3.静态多态与动态多态

3.1静态多态

        在程序编译阶段,就已经确定了程序的行为,也叫静态绑定、前期绑定(早绑定),比如:函数重载、模板。

3.2动态多态

        在程序运行时,根据程序拿到的具体类型确定程序的具体行为,调用具体的函数,比如根据基类的指针或引用指向不同类的对象,选择对应的虚函数进行调用。也叫动态绑定、后期绑定(晚绑定)。

五、单、多继承中的虚函数表

5.1单继承中的虚函数表

基类虚表:

(1)按虚函数声明顺序存放入口地址。

(2)一个类的多个对象公用同一个虚表

子类虚表:

(1)子类有自己独立的虚表,不与父类共用。

(2)子类会将基类虚表拷贝一份放入自己的虚表中。

(3)如果子类重写了基类的某个虚函数,就会用子类自己虚函数的地址去覆盖虚表中被重写的基类虚函数的地址。

(4)子类自己定义的虚函数,其地址入口会按声明顺序依次存放在虚表的末尾。

5.2多继承中的虚函数表

基类虚表:

(1)按虚函数声明顺序存放入口地址。

(2)一个类的多个对象公用同一个虚表

子类虚表:

(1)子类会将基类虚表拷贝一份放入自己的虚表中。

(2)如果子类重写了基类的某个虚函数,就会用子类自己虚函数的地址去覆盖虚表中被重写的基类虚函数的地址。

(3)子类自己新增的虚函数,会将其入口地址添加在第一张虚表之后,第一张虚表即子类第一个继承的基类所拷贝的虚表。

六、常见问题

1.什么是多态?

2.什么是重载、重写、重定义?

3.多态的实现原理?

        虚表的构造?

虚函数的调用原理:

(1)获取对象虚函数表指针(对象前4个字节)

(2)传递this指针

(3)从虚表中找到对应虚函数的入口地址

(4)调用该虚函数

4.inline函数可以是虚函数吗?

        语法上可以。不过编译器会忽略inline属性,这个函数就不再是inline,因为虚函数的地址入口需要放入到虚表中去。

5.静态成员可以是虚函数吗?

        不可以。因为静态成员函数没有this指针,使用“类名::成员函数”的调用方式无法访问虚函数表,所以静态成员不能放入虚函数表。

6.构造函数可以是虚函数吗?

        不可以。因为对象的虚函数表指针是在构造函数初始化列表阶段才初始化的。

7.析构函数可以是虚函数吗?什么场景是?

        可以。最好是把基类的析构函数定义为虚函数。场景:在继承体系中,基类的析构函数最好设置为虚函数,防止用基类的指针去销毁派生类对象时,只调用基类的析构函数而不调用子类的析构函数。

8.对象访问普通函数快还是虚函数快?

        若是普通对象,则一样快;若是指针对象或引用对象,则调用普通函数快。因为通过指针或引用访问虚函数时,需要在运行过程中去查询虚表才能确定函数入口地址,而普通对象在编译时就已经确定了函数的入口地址。

9.虚函数表是在哪个阶段生成的,存放在哪儿?

        虚函数表在编译阶段生成,一般情况存放在代码段(常量区)。

10.菱形继承的问题?虚拟原理?

        注意不要混淆虚函数表和虚基表。

11.什么是抽象类?抽象类的作用?

……

作用:抽象类规范了派生类必须重写纯虚函数,另外纯虚函数更体现出了接口的继承。

相关文章:

C++程序设计——多态:虚函数、抽象类、虚函数表

注:以下示例均是在VS2019环境下 一、多态的概念 通俗来讲,多态就是多种形态,当不同的对象去完成某个行为时,会产生出不同的状态。即不同继承关系的类对象,去调用同一函数时,产生不同的行为。 比如”叫“这…...

OpenMMLab AI实战营 第6课 语义分割与MMSegmentation

第6课 语义分割与MMSegmentation 1. 语义分割简介 任务:将图像按照物体的类别分割成不同的区域,等价于对每个像素进行分类应用 无人驾驶人像分割智能遥感医疗影像分析 语义分割 vs 实例分割 vs 全景分割 语义分割:仅考虑像素的类别&#xf…...

产业互联网是对互联网的衍生和进化,也是一次重塑和再造

互联网并不仅仅只是充当撮合和中介的角色,它应当具备更多的功能和意义。只有这样,它的发展才能够真正全面和完善。产业互联网的衍生和出现,正是在互联网进化的基础之上出现的。这是我们看到之所以会有那么多的互联网玩家投身到产业互联网的浪…...

Shell脚本之——Hadoop3单机版安装

目录 1.解压 2.文件重命名 3.配置环境变量 4.hadoop-env.sh 5.core-site.xml 6. hdfs-site.xml 7. mapred-site.xml 8.yarn-site.xml 9.完整脚本代码(注意修改主机名) 10.重启环境变量 11.初始化 12.启动服务 13.jps查询节点 1.解压 tar -zxf /opt/install/hadoo…...

代码随想录NO39 |0-1背包问题理论基础 416.分割等和子集

0-1背包问题理论基础 分割等和子集1. 0-1背包问题理论基础(二维数组实现)2. 0-1背包问题理论基础 二(一维数组实现)1. 0-1背包问题理论基础(二维数组实现) 背包问题一般分为这几种: 0-1背包问题:有n件物品和一个最多能背重量为w…...

FITC-PEG-FA,荧光素-聚乙二醇-叶酸,FA-PEG-FITC,实验室科研试剂,提供质量检测

FITC-PEG-FA,荧光素-聚乙二醇-叶酸 中文名称:荧光素-聚乙二醇-叶酸 英文名称:FITC-PEG-FA 英文别名:Fluorescein-PEG-Folic Acid 性状:基于不同的分子量,呈白色/类白色固体,或粘稠液体。 溶…...

简洁易懂:源码+实战讲解Redisson并发锁及看门狗自动续期

1 缘起 有一次同事问Redisson存储的键是否为hash? 我当时,没有看Redisson的相关源码,只知道应用, 所以没有办法回答,于是开始看看Redisson实现的源码, 顺便写了一个单机Redisson测试, 发现Redi…...

TCP 三次握手和四次挥手

✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录TCP 建立连接(三次握手)为啥不能是 4 次?为啥不能是 2 次?三次握手的意义:TCP 断开连接(四…...

JavaWeb复习

JavaWeb复习一.概述1.概念2.B/S和C/S 架构二.HTTP通信协议概述1.概念2.HTTP1.0 与 HTTP1.1 版本3.HTTP 协议组成4.常见状态码5.GET 与 POST 请求方式三.Tomcat1.Web服务器介绍2.安装(Windows)3.Tomcat目录结构4.server.xml部分配置解释四.Servlet1.概念2…...

P14 PyTorch AutoGrad

前言:激活函数与loss的梯度PyTorch 提供了Auto Grad 功能,这里系统讲解一下torch.autograd.grad系统的工作原理,了解graph 结构目录:1: require_grad False2: require_grad True3: 多层bakcward 原理4: in…...

前端报表如何实现无预览打印解决方案或静默打印

在前端开发中,除了将数据呈现后,我们往往需要为用户提供,打印,导出等能力,导出是为了存档或是二次分析,而打印则因为很多单据需要打印出来作为主要的单据来进行下一环节的票据支撑, 而前端打印可…...

Operating System Course 2 - My OS

Computer Startup process上一篇:http://t.csdn.cn/XfUKt 讲到这个启动设备的第一个扇区:引导扇区。那么引导扇区的代码长什么样子?这里得看引导扇区代码源文件bootsect.s(.s后缀文件为用汇编语言编写的源代码文件)。另…...

离散数学 课时一 命题逻辑的基本概念

1 命题 1、命题:可以判断其真值的陈述句 2、真值:真或者假(1或者0) 3、真命题:真值为真的命题 4、假命题:真值为假的命题 5、原子命题:不可以再被分解成更简单的命题 6、复合命题:由原子命题通过联结词联结…...

Word文档带有权限密码怎么办?

Word文档的权限密码指的是什么?其实这是Word文档的保护方法之一,具体指Word文档的编辑、修改受到了限制,需要输入密码才能进行。 设置了权限密码的Word文档还是可以直接打开,只有当需要编辑或者修改内容的时候,才会发…...

C++多态

1. 多态的概念1.1 概念多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态举个例子:比如买票这个行为,当普通人买票时,是全价买票&#xff1b…...

访问学者如何申请美国J1签证?

一、申请美国J1签证的步骤: 第一步:填写I901表。 填写I901表会收取SERVIS费用180美元,可以用VISA/Master卡直接网上支付。填完后打印收据单或者存成PDF后续再打印,记下I901收据编号。 第二步:DS-160表填写。 填写DS-…...

使用gitlab ci/cd来发布一个.net 项目

gitlab runner的安装和基本使用:https://bear-coding.blog.csdn.net/article/details/120591711安装并给项目配置完gitlab runner后再操作后面步骤。实现目标:master分支代码有变更的时候自动构建build。当开发人员在gitlab上给项目打一个tag标签分支的时候自动触发…...

笔试题-2023-蔚来-数字芯片设计【纯净题目版】

回到首页:2023 数字IC设计秋招复盘——数十家公司笔试题、面试实录 推荐内容:数字IC设计学习比较实用的资料推荐 题目背景 笔试时间:2022.08.24应聘岗位:校招-芯片逻辑综合工程师-智能硬件笔试时长:90min笔试平台:nowcoder牛客网题目类型:不定项选择题(15道)、填空题…...

ThreadLocal 详解

ThreadLocal简介JDK源码对ThreadLocal类的注释如下:ThreadLocal提供线程局部变量,使得每个线程都有自己的、独立初始化的变量副本ThreadLocal实例通常是类中的private static字段,用于将状态与线程相关联,如用户ID、事务ID只要线程…...

【Java 面试合集】重写以及重载有什么区别能简单说说嘛

重写以及重载有什么区别能简单说说嘛 前述 这是一道非常基础的面试题,我们在回答的过程中一定要逐一横向比较。 从方法的 修饰符,返回值,方法名,含义,参数等方面进行逐一分析来比较不同。 话不多话,看下…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...