【C++ | 抽象类】纯虚函数 和 抽象基类,为什么需要抽象基类
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 抽象基类 和 纯虚函数 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:
本文未经允许,不得转发!!!
目录
- 🎄一、概述
- 🎄二、纯虚函数
- 🎄三、抽象基类
- 🎄四、为什么需要抽象类
- 🎄五、总结

![]()
🎄一、概述
在生活中,有时会使用到比较抽象的词语,例如下面这个场景:
A:帮我把那个“东西”拿过来。
B:你是说,桌面的那个杯子吗?
A:是的。
这个场景中的“东西”就属于抽象的词语。而在C++编程中,有时也会出现这样抽象的语法。例如,我们可能会定义一个“动物”基类,但代码中不会定义一个“动物”的实例,而是将“动物”基类派生出“狗”、“猫”等派生类,再使用派生类去实例化。
本文主要介绍下面几个内容:
1、什么是纯虚函数?
2、什么是抽象基类?
3、为什么需要抽象基类?
![]()
🎄二、纯虚函数
上篇文章:【C++ | 虚函数】虚函数详解 及 例子代码演示(包含虚函数使用、动态绑定、虚函数表、虚表指针),我们详细地介绍了虚函数以及C++怎样实现虚函数的,但有一个也是很重要的知识点没在上篇文章介绍,这个知识点就是 纯虚函数。
纯虚函数:本质上也是虚函数,在虚函数的函数原型的分号前加上=0就可以将一个虚函数说明为纯虚函数。
下面代码声明了一个虚函数 eat:
virtual void eat() =0;
纯虚函数的特点:
1、纯虚函数声明就是在函数原型分号前加=0;
2、纯虚函数允许只有声明,没有定义(实现);
3、纯虚函数可以没有定义,也可以有定义,但纯虚函数的定义只能在类外。
4、只有虚函数可以加=0,非虚函数加=0会编译报错:error: initializer specified for non-virtual method
🌰举例子
// g++ 24_pure_virtual.cpp
#include <iostream>
using namespace std;class CAnimal{
public:// 1、纯虚函数声明就是在函数原型分号前加`=0`// 2、纯虚函数允许只有声明,没有定义(实现);virtual void eat() =0; virtual void run() =0;
};// 3、纯虚函数的定义只能在类外。
inline void CAnimal::run()
{cout << "Animal run" << endl;
}int main ()
{}
![]()
🎄三、抽象基类
抽象基类:英文名称是abstract base class,缩写为ABC。抽象基类是包含了至少一个纯虚函数的基类,在代码中只能用来做基类,不能用来实例化对象。
抽象基类虽然不能实例化对象,但可以定义抽象基类的指针或引用,以此来管理其派生类对象。
抽象基类的特点:
1、抽象基类至少有一个纯虚函数;
2、抽象基类不能创建对象;
3、抽象基类要求派生类必须重写纯虚函数,以此来规范派生类的接口(函数);
4、派生类必须重写抽象基类中的所有纯虚函数,否则也是抽象类,无法实例化对象。
5、抽象基类的纯虚函数一般没有定义,即使有定义也没法创建对象去调用。
🌰举例子
// g++ 24_pure_virtual2.cpp
#include <iostream>
using namespace std;class CAnimal{
public:virtual void eat() =0; // 纯虚函数,本类是抽象基类virtual void run() =0;
};class CCat : public CAnimal{
public:// 没有重写基类的所有纯虚函数,本类是抽象类virtual void eat(){cout << "cat eat" << endl;}
};class CDog : public CAnimal{
public:// 重写基类的所有纯虚函数,本类不是抽象类virtual void eat(){cout << "dog eat" << endl;}virtual void run(){cout << "dog run" << endl;}
};// 纯虚函数的定义只能在类外。
inline void CAnimal::run()
{cout << "Animal run" << endl;
}int main ()
{//CAnimal animal; // 报错:error: cannot declare variable ‘animal’ to be of abstract type ‘CAnimal’//CCat cat; // 报错:error: cannot declare variable ‘cat’ to be of abstract type ‘CCat’CDog dog;CAnimal *pAnimal = &dog;pAnimal->run();pAnimal->CAnimal::run(); // 指定调用基类的run
}
运行结果:

![]()
🎄四、为什么需要抽象类
之前一直在想,很多代码明明使用普通类也可以,为什么需要定义抽象类呢?
需要定义抽象基类的几个原因:
- 1、将接口与实现分离。接口是软件产品最有价值的资源,设计接口比实现接口需要耗费更昂贵的成本。因此,要将接口保护起来,以免在针对客户需求修改实现的时候,程序员不小心把接口破坏掉。
我们将一些必要的接口(函数)定义在抽象类,要求派生类必须按照这个格式去重写,如果不重写就休想创建对象。也就是说,抽象类将具体实现延迟到子类中,提供代码重用性和一定程度的设计约束。 - 2、避免某些基类被实例化是不合理的。例如“形状”这个基类,被实例化之后反而会让人相当费解,所以干脆将“形状”这个类定义为抽象类,由它派生出正方形,三角形等子类。
- 3、提示作用,当我们看到抽象基类就会知道其派生类一定会重写纯虚函数,而且也会去找抽象类的指针或引用,看看是否实现多态。其次,看到抽象类也知道它不会定义对象,也就不会去代码里找抽象类的对象了。
![]()
🎄五、总结
本文介绍了C++的纯虚函数、抽象基类,以及怎样使用它们,最后介绍了需要抽象基类的原因。

如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
参考:
《C++ primer》
《C++ primer plus》
C++为什么要定义抽象基类?
为什么需要抽象类和接口?
为什么使用抽象类?有什么好处?
相关文章:
【C++ | 抽象类】纯虚函数 和 抽象基类,为什么需要抽象基类
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
DP(7) | 打家劫舍① | Java | LeetCode 198, 213, 337 做题总结(未完)
打家劫舍问题 来源于代码随想录:https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html#%E6%80%9D%E8%B7%AF ① 确定dp数组(dp table)以及下标的含义 dp[i]:考虑下标i(包括i)以内的房…...
人工智能算法工程师(中级)课程17-模型的量化与部署之剪枝技巧与代码详解
大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(中级)课程17-模型的量化与部署之剪枝技巧与代码详解。模型剪枝是深度学习领域中一项关键的技术,旨在减少神经网络中的冗余权重,从而降低计算成本和内存占用,同…...
JavaScript 实例:掌握编程技巧
JavaScript 实例:掌握编程技巧 JavaScript 是一种广泛使用的编程语言,它为网页添加交互性,是现代网络开发的重要组成部分。本文将通过一系列实例,帮助您更好地理解和掌握 JavaScript 的核心概念和编程技巧。 基础实例:变量和数据类型 首先,让我们从最基础的开始。Java…...
自己做小项目时,配置的Maven需要用阿里云私服加速Jar包的下载
在我的IDEA中,maven配置在了这个地址,然后我需要去这个地址下找到settings.xml的maven配置文件来配置以下的阿里云私服地址来加速jar包的下载!【不然就是下N年很慢!】...
Linux笔记之time命令测量命令的执行时间
Linux笔记之time命令测量命令的执行时间 在Linux中,time命令用于测量命令的执行时间。这对于分析和优化脚本或程序的性能非常有用。time命令会显示三个主要时间指标: real: 从命令开始到结束的实际时间(也称为挂钟时间)。user: …...
《基于 CDC、Spark Streaming、Kafka 实现患者指标采集》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
重要的单元测试
👽System.out.println(“👋🏼嗨,大家好,我是代码不会敲的小符,目前工作于上海某电商服务公司…”); 📚System.out.println(“🎈如果文章中有错误的地方,恳请大家指正&…...
什么是diff算法?
Diff算法,全称为Difference算法,是一种用于比较和查找两个对象(如文本、源代码、数据结构或任何形式的字符串)之间差异的算法。它在多个领域有着广泛的应用,包括但不限于前端开发、版本控制系统、协同编辑工具等。以下…...
BUUCTF逆向wp [MRCTF2020]Transform
第一步 查壳。该题为64位。 第二步 进入主函数,跟进dword_40F040,它应该与关键字符串有关 分析一下: 初始化和输入 sub_402230(argc, argv, envp); 这行可能是一个初始化函数,用于设置程序环境或处理命令行参数。具体功能不明,…...
前端下载文件流 出现乱码 解决方案
1. 后端返回文件格式不是 utf-8 解决方案:后端加 2. 若添加 utf-8 后依旧乱码 请求配置中添加 responseType: arraybuffer, export function downMode() {return http.request({url: baseUrl downTemplate,method: get,responseType: arraybuffer,}); }下载 con…...
Linux/Windows 系统分区
1. Windows 系统 1.1 系统分区 系统分区也叫做磁盘分区,即分盘; 举个例子,好比家里有一个大柜子,把衣服,鞋子,袜子都放在里面,由于没有隔断,找的时候非常麻烦,找是能找…...
C/C++ xml库
文章目录 一、介绍1.1 xml 介绍1.2 xml 标准1.3 xml 教程1.4 xml 构成 二、C/C xml 库选型2.1 选型范围2.2 RapidXML2.3 tinyxml22.4 pugixml2.5 libxml 五、性能比较5.1 C xml 相关的操作有哪些5.2 rapidxml、Pugixml、TinyXML2 文件读取性能比较 六、其他问题6.1 version和 e…...
UniVue@v1.5.0版本发布:里程碑版本
前言 以后使用UniVue都推荐使用1.5.0以后的版本,这个版本之后,更新的速度将会放缓。 希望这个框架能够切实的帮助大家更好的开发游戏,做出一款好游戏!本开源项目采用的开源协议为MIT协议,完全开源化,以后也…...
在 Windows 上开发.NET MAUI 应用_2.生成你的第一个应用
先决条件 Visual Studio 2022 17.8 或更高版本,并安装了 .NET Multi-platform App UI 工作负载。 可参考上一篇文章:http://t.csdnimg.cn/n38Yy 创建应用 1.启动 Visual Studio 2022。 在开始窗口中,单击“创建新项目”以创建新项目&#…...
配置SMTP服务器的要点是什么?有哪些限制?
配置SMTP服务器安全性如何保障?如何高效配置服务器? SMTP作为电子邮件发送的核心协议,其配置对于确保邮件的成功传递和安全至关重要。AokSend将详细介绍配置SMTP服务器的关键要点,帮助读者建立一个高效、安全的邮件发送系统。 配…...
图形渲染基础-Unity渲染管线介绍
Unity中的渲染管线渲染场景主要分为三个阶段 剔除(Culling) 剔除摄像机不可见对象(视锥体剔除Frustum Culling)和被遮挡对象(遮挡剔除Occlusion Culling)。 渲染(Rendering) 将可见…...
junit mockito service
service类单元测试可以有两种方式 1、使用Autowired启用上下文的Bean走业务逻辑,适用于debug调试 2、使用InjectMocks不启用上下文依懒的Bean采用打桩的形式 打桩注意:service通常业务逻辑复杂,Bean的依懒层次可能很深,初用者常…...
k8s学习——升级后的k8s使用私有harbor仓库
升级后的k8s使用了第三方的容器管理器,安装了nerdctl工具来替代docker进行镜像管理。但是使用docker build打包并上传至harbor仓库的镜像,在部署过程中始终拉不下来,报错证书错误。通过journalctl -xe |grep kubelet 或 journalctl -xe |grep…...
Blender4.2版本正式上线,新版本的5个主要功能!
Blender刚刚推出了备受瞩目的 Blender 4.2 版本,这款软件专为那些在视觉特效、动画制作、游戏开发和可视化设计领域工作的艺术家们量身打造。作为最新的长期稳定更新,Blender 4.2 不仅稳定可靠,还引入了备受期待的“Eevee Next”实时渲染引…...
如何用5分钟彻底解决Mac菜单栏混乱?Ice菜单栏管理工具终极指南
如何用5分钟彻底解决Mac菜单栏混乱?Ice菜单栏管理工具终极指南 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 你是否曾盯着Mac屏幕顶部那密密麻麻的图标海洋感到无力?Wi-Fi图…...
CANN/asc-devkit NodeIoNum API文档
NodeIoNum 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。 项目地址: https://gitcode.com/…...
目标检测 - 从FPN到PAN:双向路径聚合如何提升特征融合效率
1. 目标检测中的特征金字塔:从FPN到PAN的进化之路 在目标检测任务中,处理多尺度目标一直是个棘手的问题。想象一下,你要在一张图片中同时识别出近处的行人、远处的车辆和更远处的交通标志,这些目标的尺寸差异可能达到数十倍。传统…...
Visual C++运行库全家桶:一站式解决Windows软件兼容性问题的终极方案
Visual C运行库全家桶:一站式解决Windows软件兼容性问题的终极方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 还在为"应用程序无法启动&qu…...
终极Visual C++运行库修复指南:一劳永逸解决Windows软件兼容性问题
终极Visual C运行库修复指南:一劳永逸解决Windows软件兼容性问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist Visual C运行库修复工具是解决Windo…...
拆解OpenWrt的.ipk安装包:从文件结构到手动安装,彻底搞懂opkg底层逻辑
OpenWrt软件包深度解析:从.ipk结构到手动安装全指南 1. OpenWrt软件包管理机制揭秘 对于OpenWrt用户来说,opkg命令是日常管理软件包的基础工具。但当你遇到网络连接问题无法在线安装,或者需要定制修改软件包时,理解其背后的工作机…...
图卷积神经网络自编码器天线优化设计方法【附代码】
✨ 本团队擅长数据搜集与处理、建模仿真、程序设计、仿真代码、EI、SCI写作与指导,毕业论文、期刊论文经验交流。 ✅ 专业定制毕设、代码 ✅如需沟通交流,点击《获取方式》 (1)天线结构图表示与变分图自编码器代理模型:…...
环境配置与基础教程:多机多卡分布式训练实战:基于 SLURM 集群调度 YOLOv11,大幅缩短训练周期
一、为什么分布式训练是 YOLOv11 落地的“必经之路” 1.1 单卡训练的困境 如果你正在使用 YOLOv11 做目标检测,那么你一定遇到过这个场景:数据集有十万张以上的图片,模型选的是 YOLOv11x,单张 A100 跑一个 epoch 要 40 分钟,完整训练 300 个 epoch 需要整整 8 天。更让人…...
半导体行业成本管理:从学习曲线到EDA工具链的实战策略
1. 行业成本与价格压力的永恒博弈在半导体这个行当里干了十几年,我越来越觉得,我们这行最核心的生存法则,不是什么高深莫测的量子物理,而是一个看似简单、实则残酷的算术题:一边是不断上涨的原材料、设备和设计成本&am…...
FGO自动化终极指南:告别枯燥刷本,每天节省3小时游戏时间
FGO自动化终极指南:告别枯燥刷本,每天节省3小时游戏时间 【免费下载链接】FGA Auto-battle app for F/GO Android 项目地址: https://gitcode.com/gh_mirrors/fg/FGA 你是否厌倦了在《Fate/Grand Order》(FGO)中重复点击刷…...
