首先说明一下我只是一个初学者,写出来的东西可能会有错误,说实在的没写过多少代码,但是我认为写代码是一个熟练的过程,一个完成思想的过程。只有有了思想,才能完成好的设计,不断的思考,不断的总结才能学到新学到的东西,才能达到更高的目标。
在C++中虚函数是指将一个类中的虚函数后面加上=0,就说明该虚函数为纯虚函数。一般该函数设置为纯虚函数,那么该函数也就没有再次定义的必要了,因为存在纯虚函数的类就是一个抽象类,是不能够创建对象的,不能创建对象也就不会主动的调用该函数,哪怕在动态绑定的情况下也不会,因此不需要为该函数定义相关的操作,实质上在此处声明只是说明在该派生类中需要重写基类的虚函数,至于是否真的复写,不要去关心。
//存在纯虚函数的类为抽象类
class AbstructClass:public Base
{
public:
//构造函数
AbstructClass(...):Base(...),...{}
//析构函数
~AbstructClass(){...}
//这就是纯虚函数,一般func在基类中就为虚函数,因此virtual也可以不写
virtual func(...) const = 0;
//保证派生类能够访问数据成员,必须设置为protected
protected:
//一些数据成员定义
...
};
抽象类的作用主要是帮助完成实际派生类的设计,为什么这么说呢?如果我们只创建一个基类,直接继承基类创建实际的派生类,存在很多的问题,为什么这么说呢?比如说我要创建一个人的类,我们每一个人都是一个人的对象,在人的基类中一般只是包含了人的共性,不可能将某一个人的特殊定义到类中,当然为了继承,肯定也会创建一系列的虚函数。如果我们每一个人都直接从该基类派生,人的个体在世界上有60多亿,我们每一个人实际上就是一个派生类,因为每一个人都不同,都有自己独特的特性(假设是一种数据对象),如果要实现这么多的派生类真的是一个不可想象的,而且我们可以知道很多人(类)实际上存在很多的相似性。
这时我们实际上就可以采用抽象类来帮忙完成我们的设计。抽象类是连接在基类和实际派生类之间的中间类,实际派生类的直接基类是抽象类,也就说说基类是实际派生类的间接基类。在抽象层中主要完成什么操作呢?抽象层中主要完成对派生类共性数据成员的定义,为了方便派生类的数据访问,必须设置为受保护访问权限,创建纯虚函数,定义构造函数,应该在初始化列表中首先创建基类对象,然后才能完成其他成员的初始化,有时候可能需要复制控制函数的实现。
在实际的派生类设计过程中就不再直接从基类继承,而是从抽象类中继承,因为抽象类中增加了一些受保护成员数据,且这些数据成员时派生类的共性,因此派生类中可以很方便的访问。同时在该派生类中就应该完成虚函数的复写操作,因为动态绑定以后会直接调用该版本的虚函数。当然有时候也要完成复制控制函数的定义。当然可以设计很多基于抽象类的派生类。当然在派生类中也可以增加自己的数据成员。
//实际派生类从抽象类中继承
class ActualClass : public AbstructClass
{
public:
ActualClass(...):AbstructClass(...),...{}
//派生类中复写虚函数
func()
{...}
private:
//派生类的一些数据
...
};
基本的思想如下图所示:
从上面的图可知,我们可以在实际的派生类与基类之间增加一个中间层,这种实现方式不仅能够更好的隐藏数据,而且比较好的解决了我们上面提到的派生类过实现过于复杂的问题。因此我们可以认为抽象类实际上就是一个分层设计的方法,也可以认为是一个分成更加精细子类的方式方法,也就是说在基类的基础上将对象分成很多子类(抽象类),然后在各个子类下设计新的派生类。比如在图中的抽象类1,抽象类2是不同的,是两种不同的分类,这候我们给予两个抽象类的派生类当然也就存在了差别。这样实现的好处能够避免很多的重复代码。
就假设我们要实现一个比较简单的校园人类,假设已经存在了一个人的基类(Base),那么学校的人存在很多的特征,但是我认为主要分成了3大类,主要是学生、教师、服务人员,因此可以再基类的基础上派生出三个抽象类,Studtent, Teacher, Service,就如同上面的抽象类1,抽象类2,抽象类3。这时候设计一个实际的派生类也就减小了很多的冗余。但是我们觉得还是会存在很多的相似之处,比如学生类而言,还是可以再分,可以分为男女,这样分并不是最好的,我们实际上可以按照专业分,这时候又可以再Student的基础上派生出不同的学生专业抽象类,在各个专业下又可以分为博士、研究生、大学生抽象类,在这些抽象类的基础上还可以分为男女抽象类,到这时就可以直接完成具体每一个派生类的实现啦,这时候的直接基类就是男女学生抽象类,这样就形成了一个多层次的分解问题,将一个大的问题分解成了很多的子类,在子类的基础上在分成更细的子类,最后到达一个精细的抽象子类,这时实现一个具体的派生类就会非常的方便。也就减少了很多的冗余代码,虽然设计的类更多了,但是实现的方式会更加的容易。所以说分层设计的思想是一个重要的思想,分层就能将一个大问题逐步喜欢,而在C++中纯虚函数(抽象类)的运用就能够巧妙的解决这种多层次设计问题。所以说我们的分层设计不仅仅只是单一层的,也可以是多层次的。如下图所示:
因此我们应该掌握C++中这种纯虚函数的用法,只有掌握了这种设计方法才能实现更加漂亮的类设计。当然上面只是我的一些遐想。具体的实现过程还需要在经后的实践中练习。在类的设计中多增加抽象类能够简化类的冗余度,使得类能更加方便的被继承。从上面的结果我们可以将分层设计看做一个树形结构,基类就是树的根,而实际的派生类是就是叶,而那些中间的抽象层就是节点。