虚函数,抽象基类

news2024/9/29 7:32:09

编译器处理虚函数的方法:

给每个对象添加一个隐藏成员,隐藏成员保存了一个指向函数地址的数组指针,数组被称为虚函数表,虚函数表存储了为类对象声明的虚函数的地址,比如基类包含一个指针,该指针指向基类中所有的虚函数的地址查找表,派生类将继承这个虚函数地址表,如果重新定义了虚函数,那么派生类的虚函数表中相应的函数地址会被替换,调用虚方法的时候,函数调用的就是这个虚地址里的函数,由于被替换,所以可以用基类指针调用派生类方法,调用虚函数时,程序将查看虚函数表中的地址,并转向相应的函数地址表,

总之使用虚函数的时候,在内存和执行速度上都有一定的成本,包括:

每个对象都将增大,增大量为存储虚函数地址的数组的空间;

对于每个类,编译器都要创建一个虚函数地址表;

对于每个函数调用,都需要执行一项额外操作,即到表中查找地址;

虽然非虚函数比虚函数效率高,但不具备动态联编功能;

析构函数必须是虚析构函数:这是由于基类指针指向派生类对象造成的;

虚函数与抽象基类是不一样的;

友元不能是虚函数,只有成员函数才能是虚函数,

如果定义的类被用作基类,则应该将那些在派生类中重新定义的方法声明为虚的,析构函数是一定会被重载的,因此析构函数必须是虚函数;构造函数不能是虚函数,调用顺序是先调用基类构造函数,在调用派生类构造函数,如果是虚方法,则将调用派生类的构造函数,然后调用基类的构造函数,这与继承的机制相反;

如果派生类中重新定义的函数与基类虚函数的函数特征标不同即重载,那么将隐藏基类虚函数,根据返回类型协变,如果只是修改返回值,将不会隐藏基类虚函数,

如果确实有必要重载基类虚函数(函数特征标不同),那么应该在派生类中重载所有的基类版本,如果只重载一个版本,那么另外的将被隐藏,

 如上,Hovel必须重写所有的基类虚函数,这也不能通过作用域解析运算符来调用,

总结虚函数注意:

当定义为虚函数时,通过指针或引用调用时,调用的函数为指向对象的类型中的函数,而不是指针的类型下的函数;

虚函数表:虚函数的调用方式:指针在指针指向的对象的虚函数数组内找到要调用的函数指针地址,然后调用,所以虚函数可以调用指针指向类型的函数;由于虚函数表的存在,他只与对象有关,

隐藏基类方法:如果子类对虚函数进行重载,将隐藏基类的虚函数,因此如果重载,则必须重新定义所有的同名基类虚函数;

总的来说,虚函数是对于单继承模式下函数多态的一种拓展,当出现菱形继承时情况还会复杂一些;

抽象基类:

is-a关系是数学中的包含关系,一个集合属于另一个集合,但是当两个集合出现相交时就有问题了,比如圆是特殊的椭圆,但椭圆类有两个焦点,圆只有一个圆心,即属性成员出现了冲突,除此之外圆和椭圆可以发生的动作也是不同的,是不能通过函数重载来解决的, 单独定义两个类似乎更简单一些;

抽象基类说明:

但是圆和椭圆是由共同点的,也就是说这种相交关系更像是同辈,而不是父子,因此可以给他们两个指定一个基类,包含他们的交集,有时这种类不需要被实例化,此时我们称这种类为抽象基类,比如圆和椭圆的抽象基类,按理来说他是一个图形,但它只包括了中心点的坐标,他没有半径,长短焦距这些参数,那么他其实无法实例化为一个图形,这时它理论上就无法被实例化,同时实际上他也没有必要被实例化,那么他就成为一个抽象基类就好了,这点我们可以这么来举例:人和狮子是哺乳动物的派生类,但哺乳动物无法被实例化,他有几个脚?几个眼睛?什么样的运动方式?都没有,怎么运动?如果没有运动,只是声明的话是没有内存空间的,程序就没法访问它,对于没有实际意义的动作,就把他们声明为纯虚函数,对于没有意义的属性,直接不声明它,那么哺乳动物就是一个它通过加入纯虚函数来实现,

纯虚函数的结尾处为 =0;如下图中的

virtual double Area()const =0;

纯虚函数也可以有定义,但他不能同时是内联的,即不能再类声明中定义;

概念称呼:哺乳动物是抽象类,人和狮子就是具体类,即可以创建对象的类,

成为具体类的方法:要想成为具体类就必须重写所有的基类的纯虚函数;

所有的当类与动态内存分配结合起来时,情况就会很微妙;如果再加上继承,

动态内存分配涉及到复制构造函数,析构函数,重载赋值运算符,当出现需要动态内存分配的初始化的指针成员时,必须重载这三个指令集,

否则会出现内存泄漏(析构函数)和浅拷贝(赋值运算符,复制构造函数)以及重复清理堆空间(析构函数),

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

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

相关文章

阿里巴巴变革,盒马“一马当先”

配图来自canva可画 随着数字经济成为当前经济社会发展的“新宠”,诸多数字企业也开始走上了发展的快车道。而作为国内互联网大厂的阿里巴巴集团,为了打造数字经济时代的商业、金融、物流、云计算和大数据等新一代商业基础设施,就于前不久启动…

Javawed第一章:Web前端的入门理论

目录 前言 一.wed 💖wed是什么? 💖 wed的分类 二.HTML 和 CSS 💖HTML的介绍 HTML的标签 💖CSS的介绍 常用基本标签 💖实践 HTML结构标签特点 三.JavaScript 💖JavaScript的介绍 &…

SOLIDWORKS仿真数据清扫工具

我们来聊下SOLIDWORKS仿真数据清扫工具。与 SOLIDWORKS 软件一起安装的一个鲜为人知的工具是 Simulation Cleaning Utility。该实用工具可用于在 SOLIDWORKS 零件或装配文件中永远删除任何仿真数据,包括仿真设置和后处理信息。 SOLIDWORKS仿真数据清扫工具工具可以…

阻塞队列(消息队列)

1、阻塞队列 队列是一种先进先出的数据结构。而阻塞队列也是一种特殊的队列,也遵守”先进先出“的原则。 阻塞队列是一种线程安全的的数据结构,并且具有以下特性: 1、队列往进写元素是从队尾插入,队首取出 2、当插入元素的时候…

Python面向对象编程基础知识和示例代码

文章目录 对象(Object)示例代码一 类的成员方法(Method)示例代码二 类和对象(Class and Object):示例代码三 构造方法(Constructor):示例代码四 魔术方法&…

JUC简介

1、JUC介绍 JUC (java.util.concurrent)是在并发编程中使用的工具类,主要包括以下三个 (1)java.util.concurrent (2)java.util.concurrent.atomic 原子性:不可分割。Int i0; i, (3)…

MySQL——函数与约束的讲解

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​ 前言 本章将会讲解MySQL数据库的函数与约束的讲解。 一.函数 函数 是指一段可以直接被另一…

渗透测试面试题汇总

2023年快过去一半了,不知道小伙伴们有没有找到自己心仪的工作呀【doge】,本文总结了常见的安全岗位面试题,方便各位复习。祝各位事业顺利,财运亨通。在网络安全的道路上越走越远! 所有的资料都整理成了PDF&#xff0c…

DCN v1阅读笔记

DCN v1即 Deformable Convolutional Networks。 视觉识别(例如对象检测和语义分割)中的一个关键挑战是如何适应物体尺度、姿态、视角和零件变形中的几何变化或模型几何变换。卷积神经网络(CNN)构建模块中为固定几何结构&#xff1…

神经网络基础

文章目录 一、神经网络基础1.得分函数 f(xi;W,b)1)从输入到输出的映射2)数学表示3)计算方法4)多组权重参数构成了决策边界 2.损失函数 L3.前向传播4.Softmax分类器 梯度下降2.反向传播 一、神经网络基础 回归任务:最终…

软件测试技能,JMeter压力测试教程,JDBC配置连接mysql数据库(十)

前言 使用jmeter压测接口的时候,有时候需要批量造数据,需使用jmeter连数据库造对应的测试数据 或者测试结束后,对测试的数据还原,删掉一些垃圾数据,都会用到连接数据库执行sql的操作 一、JDBC 连接配置 添加配置元…

7-WebApis-2

Web APIs - 2 掌握事件绑定处理和事件对象,完成常见网页交互 事件监听事件类型事件对象拓展知识综合案例 事件监听 以前写的代码都是自动执行的,我们希望一段代码在某个特定的时机才去执行,比如 点击按钮可以弹出警示框比如鼠标经过显示下拉…

通过easyui的filebox上传文件

本篇文章重点分享一下怎么通过easyui的filebox实现文件上传的功能&#xff0c;从前端代码到后端接口都会展示给大家。 1、form表单同步上传 传统的文件上传会把<input type"file" />放到一个<form></form>里&#xff0c;设置form表单的提交方式为…

开源代码分享(5)—配电网重构的启发式算法(附matlab代码)

来源于文献IEEE TRANSACTIONS ON POWER SYSTEMS期刊文献的开源代码。 摘要&#xff1a;本文提出了一种两阶段的启发式计算方法&#xff0c;可以在最小的计算时间内重新配置一个径向分布网络。所有的网络交换机在操作的初始阶段都是关闭的&#xff0c;并提出了一个顺序的开关开闸…

基于SSM+jsp的教学质量评价系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

Origin如何绘制三维离散点并拟合曲面?

文章目录 0.引言1.准备数据2.三维离散点参数设置并绘图3.拟合曲面参数设置并绘图 0.引言 在数据统计分析中&#xff0c;有时希望知道一个因变量在两个自变量变化情况下的变化情况&#xff0c;这时可以绘制散点图&#xff0c;观察基础情况&#xff0c;进一步可以拟合散点&#x…

腾讯安全吴石:基于威胁情报构建免疫体系,助力企业稳步迈向智能安全新阶段

6月13日&#xff0c;腾讯安全、腾讯研究院联合IDC、《中国信息安全》杂志社、CIO时代、新基建创新研究院等多家权威机构、媒体共同发起“数字安全免疫力研讨论坛”&#xff0c;聚合产学研各界专家学者探讨数字安全建设新范式。论坛上&#xff0c;腾讯安全联合IDC发布“数字安全…

【物联网】使用RabbitMQ作为MQTT服务端并自定义设备连接权限

文章目录 项目背景一、部署RabbiqMQ二、设备连接鉴权1.开启插件2.修改配置3.连接鉴权4.消息鉴权 总结 项目背景 最近公司启动了一个新的物联网项目&#xff0c;使用MQTT协议与设备通信&#xff0c;在比较了各大MQTT服务后&#xff0c;决定选用开源的RabbitMQ搭建我们的服务端。…

最专业的敏捷需求管理工具推荐

为了协助大家找到合适的需求管理工具&#xff0c;我们选择了国内外几款款工具作比对&#xff1a; Leangoo领歌敏捷工具 Jama Software Visure Requirements IBM DOORS Next ReqSuite RM ReQtest Xebrio Orcanos Helix RM SpiraTeam Accompa Innoslate Leangoo领歌…

Python学习——元组

一、元组的定义 这部分就没有增、删、改操作了&#xff0c;是因为元组是一个不可变序列&#xff0c;元组也是Python内置的数据结构之一。 补充&#xff1a;关于可变序列与不可变序列 可变序列是指可以对序列进行增、删、改的操作&#xff0c;对象地址不发生变化。常见的可变序列…