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

【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++为什么要定义抽象基类?
为什么需要抽象类和接口?
为什么使用抽象类?有什么好处?

http://www.lryc.cn/news/402506.html

相关文章:

  • DP(7) | 打家劫舍① | Java | LeetCode 198, 213, 337 做题总结(未完)
  • 人工智能算法工程师(中级)课程17-模型的量化与部署之剪枝技巧与代码详解
  • JavaScript 实例:掌握编程技巧
  • 自己做小项目时,配置的Maven需要用阿里云私服加速Jar包的下载
  • Linux笔记之time命令测量命令的执行时间
  • 《基于 CDC、Spark Streaming、Kafka 实现患者指标采集》
  • 重要的单元测试
  • 什么是diff算法?
  • BUUCTF逆向wp [MRCTF2020]Transform
  • 前端下载文件流 出现乱码 解决方案
  • Linux/Windows 系统分区
  • C/C++ xml库
  • UniVue@v1.5.0版本发布:里程碑版本
  • 在 Windows 上开发.NET MAUI 应用_2.生成你的第一个应用
  • 配置SMTP服务器的要点是什么?有哪些限制?
  • 图形渲染基础-Unity渲染管线介绍
  • junit mockito service
  • k8s学习——升级后的k8s使用私有harbor仓库
  • Blender4.2版本正式上线,新版本的5个主要功能!
  • 【python基础】基本数据类型
  • 应用层——HTTP
  • 剧本杀小程序搭建,为商家带来新的收益方向
  • 十六、【机器学习】【监督学习】- 支持向量回归 (SVR)
  • 基于FPGA的多路选择器
  • 面经学习(杭州实在智能实习)
  • mysql、oracle、db2数据库连接参数
  • redis缓存击穿和缓存穿透的封装、缓存更新的CacheAside方案、数据预热
  • ArcGIS Pro SDK (九)几何 5 多边形
  • Docker 镜像使用和安装
  • JAVA:Filer过滤器+案例:请求IP访问限制和请求返回值修改