【c++】虚函数,纯虚函数,抽象类

news2025/2/24 3:24:33

这里写目录标题

  • 虚函数
  • 纯虚函数
  • 抽象类
    • 为什么抽象类不能创建对象?
    • 注意点:
  • 接口
  • 类如何设计
  • 虚析构
    • 总结:
  • 构造函数为什么不能是虚函数
  • 有虚函数的对象创建过程

虚函数

虚函数:给成员函数前面加上virtual关键字。

1.派生类中定义虚函数必须与基类中的虚函数同名外,还必须同参数表,同返回类型。否则被认为是重载,而不是重写。如基类中返回基类指针,派生类中返回派生类指针是允许的,这是一个例外(协变)。

2.只有类的成员函数才能说明为虚函数。这是因为虚函数仅适用于有继承关系的类对象。友元函数和全局函数不能作为虚函数。

3.静态成员函数,是所有同一类对象共有,不受限于某个对象,不能作为虚函数。

4.内联函数每个对象一个拷贝,无映射关系,不能作为虚函数。

5.构造函数(拷贝构造,移动构造)不能作为虚函数。因为构造函数的另一个作用是设置虚表指针。

6.析构函数可定义为虚函数,在基类中及其派生类中都获取系统资源时时,必须把析构函数定义为虚函数,实现撤消对象时的多态性。

7.实现动态多态性时,必须使用基类类型的指针变量或引用,使该指针指向该基类的不同派生类的对象,并通过该指针指向虚函数,才能实现动态的多态性。

8.虚函数执行速度要稍慢一些,为了实现多态性,每一个派生类中均要保存相应虚函数的入口地址表,函数的调用机制也是间接实现。所以多态性总是要付出一定代价,但通用性是一个更高的目标。

9.如果虚函数定义放在类外,virtual只能加在函数声明前面,不能再加在函数定义前面。

10.如果不使用继承和多态,那么就把函数中的virtual关键字去掉,加上的话virtual也没必要,还会增大程序的开销。

纯虚函数

纯虚函数:没有具体实现的虚成员函数

定义纯虚函数的一般格式为:

virtual  返回类型  函数名(参数表) = 0;

“=0"表明程序员将不定义该函数,函数声明是为派生类保留一个位置。”=0"本质上是将指向函数体的指针定为NULL(不同编译器的处理不同)。
告诉编译器我们不实现这个函数,由派生类来实现。

抽象类

含义纯虚函数的类是抽象类

1.抽象类不能实例化对象
2.派生类继承了抽象类,则必须把抽象类中的纯虚函数实现了,否则也不能创建对象
3.在程序设计时,抽象类一般都做为基类来使用
当基类继承抽象类时,必须把抽象类中的所有纯虚函数进行重写,如果有一个没有重写,那么基类就是抽象类,全部实现之后,就称为(实现类)
4.抽象类不能做参数类型函数返回值类型或显示类型转换,抽象类型可以定义指针和引用(可以指向它不同的派生对象,以实现运行时多态)

应用类型:不提供派生也不提供继承
节点类型:提供继承和多态的继承(有虚函数),但没有纯虚函数
抽象类型:抽象类,只能用作基类
接口类:没有属性,所有函数都是纯抽象函数
实现类:继承了接口或者抽象类,实现了纯虚函数

为什么抽象类不能创建对象?

纯虚函数没实现时,对应的该函数指向nullpter(不同的环境实现不同),当创建对象时,进行查虚表,当它的函数为nullpter时,则会报错(纯虚函数会在虚表中保留一个位置,让派生类实现虚表时,把它对该函数的具体实现的地址填充进去它)
visaul stdio的实现:它则把这些函数指向一个函数(默认的缺省的纯虚函数,调用时会抛出异常)

注意点:

class Base
{
public:
	virtual void fun() = 0;
	virtual ~Base(){}
};
class Child :public Base
{
public:
	virtual void fun()const {}
	virtual ~Child(){}
};

Child 可以创建对象吗?

不能,因为这是同名隐藏(两个函数的参数列表不同),不属于同名覆盖。去掉const则就可以了

接口

类中全部都是成员方法,没有属性,而且成员方法全部都是纯虚函数

类如何设计

  • 有时希望派生类只继承成员函数的接口(声明),纯虚函数。
  • 有时希望派生类同时继承函数的接口和实现,但允许派生类改写实现,虚函数。
  • 有时则希望同时继承接口和实现,并且不允许派生类改写任何东西,非虚函数。

申明纯虚函数的目的,使派生类继承函数的接口和强制性实现

虚析构

如果抽象类里面有虚函数,建议把析构函数定义成虚函数,

防止出现内存泄漏

using namespace std;
class Base
{
public:
	 virtual ~Base() { cout << "delete base" << endl; }
};
class Child :public Base
{
public:
	
	 ~Child(){ cout << "delete Child" << endl; }
};
int main()
{
	Base * c = new Child();
	delete c;
	return 0;
}

运行结果
在这里插入图片描述
如果没虚析构的话

using namespace std;
class Base
{
public:
	  ~Base() { cout << "delete base" << endl; }
};
class Child :public Base
{
public:
	
	 ~Child(){ cout << "delete Child" << endl; }
};
int main()
{
	Base * c = new Child();
	delete c;
	return 0;
}

在这里插入图片描述

总结:

(1)如果父类的析构函数不加virtual关键字
当父类的析构函数不声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,只调动父类的析构函数,而不调动子类的析构函数。
(2)如果父类的析构函数加virtual关键字
当父类的析构函数声明成虚析构函数的时候,当子类继承父类,父类的指针指向子类时,delete掉父类的指针,先调动子类的析构函数,再调动父类的析构函数。

构造函数为什么不能是虚函数

因为构造函数的一个作用就是设置虚表指针,如果把构造函数设置成虚函数,那么构造函数将在虚表中存着,那么在调用构造函数的时候,虚表指针还没有设置,这样就无法找到虚表,就无法调用构造函数,而要设置虚表指针,就必须得调用构造函数,此时就已经产生矛盾了,所以构造函数不能定义为虚函数。

有虚函数的对象创建过程

1.确定this指针。(先确定this指针才可以对之后的进行构建,靠ecx传递过来)
2.如果有虚函数,则让虚表指针指向虚函数表(存放在.data)
3.构造其它成员属性

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

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

相关文章

RS485电工详解

串口数据帧我们学过&#xff0c;但到RS485是不是就卡壳了&#xff1f; 空闲状态&#xff1a;AB线悬浮在2.3V的样子。GND是0V&#xff0c;5V是4.75v 工作时&#xff0c;AB线在2.3v上做逻辑01&#xff08;-2v&#xff0c;2v&#xff09;跳变。 这图是不是还不太好理解&#xff1…

Spring事务数据库连接池流程原理详细分析

文章目录 文章目录文章目录[toc]▌Spring事务管理环境搭建标准配置声明式事务总结▌SqlSessionFactoryXML 中构建 SqlSessionFactory获得 SqlSession 的实例代码实现▌作用域&#xff08;Scope&#xff09;和生命周期SqlSessionFactoryBuilder&#xff08;构造器&#xff09;Sq…

Android App开发中OpenGL三维投影的讲解及实现(附源码和演示 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、三维投影 OpenGL&#xff0c;定义了跨语言跨平台的图形程序接口&#xff0c;对于Android开发者来说&#xff0c;OpenGL就是用来绘制三维图形的技术手段。当然OpenGL并不仅限于展示静止的三维图形&#xff0c;也能用来播…

【0基础百日刷题】洛谷刷题知识拾遗

百日刷题一.洛谷刷题得1.P1420差分数组2.P2669数列求和3.P1307数字反转4.P5725三角形5.P1980计数问题6.P1217回文质数刷题得意义&#xff1a; 有时候会发现一个简单的题目总是通不过测试&#xff0c;调试一次 就能找出一处bug。这都是我们编程时对逻辑的思考不充分而导致的失误…

听说,清华毕业分享出Redis实战视频及文档,共2.3G

前言 首先我们先来看一下redis的概念&#xff1a; Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。从2010…

【App自动化测试】(三)使用Appium进行自动化用例录制

目录1. Appium Inspctor 功能2. Appium inspector 页面结构3. 使用Appium Inspctor 进行用例录制3.1 获取 app 的信息3.2 配置待测应用3.3 使用Appium Inspector进行自动化脚本录制3.3.1 操作步骤3.3.2 自动化测试用例结构分析3.3.2.1 Appium Inspector生成用例脚本3.3.2.2 对A…

数据结构-难点突破(C++实现并查集+路径优化,详解哈夫曼编码树)

文章目录1. 并查集2. 哈夫曼编码树1. 并查集 并查集是一个多棵树的集合&#xff08;森林&#xff09;。 并查集由多个集合构成&#xff0c;每一个集合就是一颗树。 并&#xff1a;合并多个集合。查&#xff1a;判断两个值是否再一个集合中。 每棵树存在数组中&#xff0c;使…

js 中的 Event Loop 以及 宏任务 与 微任务

目录前言1、JS 的 执行引擎 与 执行环境2、js 是单线程的一、事件循环&#xff08;Event Loop&#xff09;二、任务队列三、宏任务 与 微任务1、宏任务2、微任务3、宏任务与微任务的运行机制四、Event Loop 实例案例一案例二前言 1、JS 的 执行引擎 与 执行环境 简单来说&…

SpringCloud微服务(八)——OpenFeign服务调用

OpenFeign服务调用 SpringCloud github官网&#xff1a;https://github.com/spring-cloud/spring-cloud-openfeign Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解&#xff0c;比如&#xf…

基于java+springboot+mybatis+vue+elementui的人职匹配推荐系统

项目介绍 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff0c;对于人职匹配推荐系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了人职匹配推荐系统&#xff0c;它彻底改变…

分享一下前几个月我做的超炫的登录页面

先给大家看看登录页面的效果演示 这个登录页面分为三个部分&#xff08;页面切换&#xff1a;连续按五次V&#xff0c;大小写都可以&#xff09; 第一个&#xff08;最初的鱼儿游动页面&#xff09; 登录、切换页面、和鱼儿游动这个页面的代码就不放在这里了&#xff0c;这个虽…

RabbitMQ 入门案例项目

写在前面 本文不作消息队列的实现原理、异步处理优劣、rabbitmq安装说明、消息工作模式等内容分析&#xff0c;只讲述rabbitmq实际开发中的步骤说明&#xff0c;帮助同学快速上手体验消息队列的使用。 本文使用SpringAMQP&#xff0c;并非rabbitmq官方文档上的原生http请求连…

Jupyter notebook在超算平台上使用的详细教程

Jupyter Notebook 的本质是一个 Web 应用程序&#xff0c;便于创建和共享文学化程序文档&#xff0c;支持实时代码&#xff0c;数学方程&#xff0c;可视化和 markdown。 用途包括&#xff1a;数据清理和转换&#xff0c;数值模拟&#xff0c;统计建模&#xff0c;机器学习等等…

LeetCode 数据结构与算法:最大子数组和

打开我的题库&#xff0c;调为简单难度。 计算最大子数&#xff0c;直接给我难住。 报错铺满屏幕&#xff0c;凝望没有思路。 缝缝补补做出&#xff0c;击败零个用户。 翻阅评论找补&#xff0c;令我勃然大怒。 打开思维第一步&#xff0c;编写代码求数组&#xff0c; …

报错解决:Process finished with exit code -1073741819 (0xC0000005)

简单记录一下程序异常终止&#xff0c;抛出 Process finished with exit code -1073741819 (0xC0000005) 的解决方法。 一、程序中文件位置错误/缺少文件 位置错误1&#xff1a;如果使用相对路径的话&#xff0c;推荐换成绝对路径进行排查。位置错误2&#xff1a;如果使用了o…

CAN总线协议测试拓扑图

记录测试CAN总线协议&#xff0c; CAN总线目前主要应用在汽车。 记录在PC使用USB-CAN连接测试

Talk预告 | Salesforce AI研究院研究科学家徐嘉诚:文本生成中的结构化解码

本期为TechBeat人工智能社区第457期线上Talk&#xff01; 北京时间11月23日(周三)20:00&#xff0c;Salesforce AI研究院研究科学家——徐嘉诚的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “文本生成中的结构化解码”&#xff0c;届时将详细讲解…

学会用数据分析汇报工作,升职加薪指日可待

你是否每天的八小时工作时长&#xff0c;分成八瓣用&#xff0c;却仍被领导安排众多工作&#xff1f;明明做了很多事&#xff0c;领导依旧认为工作量不饱和&#xff1f;这样的现象在职场中早已司空见惯&#xff0c;不足为奇了&#xff0c;但是究其原因是什么呢&#xff1f;工作…

Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言私信~~~ 一、通过runOnUiThread快速操纵界面 因为Android规定分线程不能够直接操纵界面&#xff0c;所以它设计了处理程序工具&#xff0c;由处理程序负责在主线程和分线程之间传递数据&#xff0c;如果分线程想刷新界面&#…

精心整理16条MySQL使用规范,减少80%问题

1. 禁止使用select * 阿里开发规范中&#xff0c;有这么一句话&#xff1a; **select *** 会查询表中所有字段&#xff0c;如果表中的字段有更改&#xff0c;必须修改SQL语句&#xff0c;不然就会执行错误。 查询出非必要的字段&#xff0c;徒增磁盘IO和网络延迟。 2. 用小表…