(1)、只要当类中拥有纯虚函数,无论这个类有没有成员变量,这个类都是一个抽象类,抽象类是不能够实例化的。
(2)、当一个普通的类,继承自抽象类的时候,一定要重写父类中的所有纯虚函数,否则这个类仍然是抽象类。
(3)、被当做父类的抽象类,通常被当做API接口被提供,也常常使用抽象类的指针指向实例化的对象(父类指针指向子类对象)。
下面是一个简单的纯虚函数构成抽象类的一个例子
- #include
- #include
- #include
- using namespace std;
-
- //人类
- class people
- {
- public:
- people(string name)
- {
- this->m_name = name;
- }
- virtual ~people()
- {
- }
-
- virtual void ActShow() = 0;//不同人群的行为模式不同
- protected:
- string m_name; //每个人都有姓名
- };
-
- //学生
- class student : public people
- {
- public:
- student(string name):people(name)
- {
-
- }
- void ActShow()
- {
- cout<<"student "<
" 每天去学校学习"< - }
- };
-
- //工人
- class workers : public people
- {
- public:
- workers(string name):people(name)
- {
-
- }
- void ActShow()
- {
- cout<<"workers "<
" 每天去工地搬砖"< - }
- };
-
- int main(void)
- {
- people *p1 = new student("zhang3");
- p1->ActShow();
-
- people *p2 = new workers("li4");
- p2->ActShow();
-
- return 0;
- }
-
-
其中的people类就是一个抽象类,student类和worker类则是抽象类的一个具体实现,people类中的纯虚函数ActShow完全由子类来实现。
这里就涉及到我们的一个,在c++多态程序设计的设计思路:向抽象层靠拢的程序设计思想
业务层的代码程序设计,面向抽象类编程,降低代码耦合度。依赖倒转原则-----上层业务层和底层实现层,向中间抽象层靠拢。
main函数就相当于是我们的一个业务需求,也就是业务层。当有很多业务的时候,也会封装成接口,按照逻辑顺序放到main中执行。业务层往往不关心,底层到底是怎么实现的,只关心抽象层。比如此例中,我们业务层只需要给我两个人群,一个是学生,一个是工人,并且打印出来他们的日常行为模式。
抽象层就根据业务需求,提供一个人群类,在类中提供一个打印该人群日常行为模式的方法。抽象层也不关心底层怎么实现。
底层实现层,也就是对应学生类和工人类的具体实现。
2、C语言函数指针的语法和意义
我们常说c语言是一门高级语言,c++的底层是C语言来实现的,那么接下来我们来讨论一下,C语言是如何实现c++的多态的。
首先我们要知道学习C语言有两大块内容是绕不过去的,一个是指针,另一个是函数指针。
先回顾一下三种函数指针的写法
- #include
- #include
- #include
- using namespace std;
-
- //方式1
- typedef void (FUNC)(int, int);
-
- //方式2
- typedef void (*PFUNC)(int, int);
-
-
- void old_func(int a, int b)
- {
- cout<<"this is old_func..."<
- }
-
- int main(void)
- {
- FUNC *fp1 = NULL;
- fp1 = old_func;
- fp1(1, 2);
-
- PFUNC fp2 = NULL;
- fp2 = old_func;
- fp2(10, 20); //在调用的时候 不用考虑取*取&的问题,C语言编译器对这里优化了
-
- //方式3
- void (*fp3)(int, int) = NULL;
- fp3 = old_func;
- fp3(100, 200);
-
- return 0;
- }
-
-
执行结果没有问题,打印了三次this is old_func...
可以使用函数指针,来构成我们自己的C语言的抽象类。比如我们的抽象需求就是,完成f的一次功能调用,并给该实现传递两个参数。该功能可以是old_func,可以是其他的函数,只要满足形参列表是(int, int)且返回值是void,就可以。这样就像类似于c++中的纯虚函数
- #include
- #include
- #include
- using namespace std;
-
- //方式1
- typedef void (FUNC)(int, int);
-
- //方式2
- typedef void (*PFUNC)(int, int);
-
- void old_func(int a, int b)
- {
- cout<<"this is old_func..."<
- }
-
- void new_func(int a, int b)
- {
- printf("this is new_func...[a:%4d, b:%4d]\n", a, b);
- }
-
- //自定义的抽象框架,形参列表有三个,第一个是函数指针void(int,int),第2第3个参数就是int,int用来做函数指针的形参
- //函数指针可以使用三种方式中的任意一种
- int my_abstract_frame(PFUNC fp, int a, int b)
- {
- printf("my abstract frame...\n");
- fp(a, b);
- printf("do something else...\n -------------------\n");
-
- return 0;
- }
-
- int main(void)
- {
- #if 0
- //方式3
- void (*fp3)(int, int) = NULL;
- fp3 = old_func;
- fp3(100, 200);
- #endif
- my_abstract_frame(old_func, 666, 999);
- my_abstract_frame(new_func, 1000, 2000);
-
- return 0;
- }
-
-
上面例子中的my_abstract_frame,就相当于是c++中的抽象类。我们在my_abstract_frame的定义中规定了传入的函数指针类型PFUNC。old_func和new_func,就相当于是子类的具体实现。当我们用不同的实现,做不同的事的时候,只要把对应类型的函数名传进去就可以了。
这里也体现了一点C语言框架的思想。C程序工程业务框架的搭建者,只要定义好框架内做的事请,并规定好调用执行方法的类型,老程序员完成的旧业务old_func,新程序员不用关心old_func如何实现,只用关心自己的业务功能实现new_func,并满足方法的执行类型,塞到原有的框架里就可以了。c++中的抽象类实现,也许就是用的函数指针,这里不做深入的研究。
这样也体现了,向抽象层靠拢的程序设计思想,业务层规定好框架,底层实现层完成具体功能。
-
相关阅读:
2022.9 PAT甲级题解
基于SpringBoot的精准扶贫管理系统
前端常用设计模式
I/O软件层次
C# Onnx Yolov8 Detect Poker 扑克牌识别
js中的this举例介绍
【C#版本】微信公众号模板消息对接(二)(图文详解)
const用法精讲
基于Matlab使用雷达资源管理有效跟踪多个机动目标仿真(附源码)
Spark GC日志分析
-
原文地址:https://blog.csdn.net/tr_ainiyangyang/article/details/125878938