c++(23)纯虚函数和抽象类、C语言函数指针的语法和意义

1、纯虚函数和抽象类

(1)、只要当类中拥有纯虚函数,无论这个类有没有成员变量,这个类都是一个抽象类,抽象类是不能够实例化的

(2)、当一个普通的类,继承自抽象类的时候,一定要重写父类中的所有纯虚函数,否则这个类仍然是抽象类。

(3)、被当做父类的抽象类,通常被当做API接口被提供,也常常使用抽象类的指针指向实例化的对象(父类指针指向子类对象)。

下面是一个简单的纯虚函数构成抽象类的一个例子

#include <iostream>
#include <cstring>
#include <memory>
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 "<<m_name<<" 每天去学校学习"<<endl;
	}
};

//工人
class workers : public people
{
public:
	workers(string name):people(name)
	{
		
	}
	void ActShow()
	{
		cout<<"workers "<<m_name<<" 每天去工地搬砖"<<endl;
	}
};

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 <iostream>
#include <cstring>
#include <memory>
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..."<<endl;
}

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 <iostream>
#include <cstring>
#include <memory>
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..."<<endl;
}

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++中的抽象类实现,也许就是用的函数指针,这里不做深入的研究。

这样也体现了,向抽象层靠拢的程序设计思想,业务层规定好框架,底层实现层完成具体功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值