在本章开头介绍的RPG游戏中共有4个类。其中玩家类作为父类,剑士类、弓箭手类、魔法师类分别继承玩家类,作为子类。当我们开始游戏时,需要选择创建某一个类的对象,才能进行游戏。然而,我们的选择不应该是4个类,而应该只能在剑士类、弓箭手类或魔法师类中做出选择。因为,单纯的玩家类是抽象的、不完整的,任何一个玩家必须有一个确定的职业之后,才能确定他的具体技能。又比如学生类,它也是非常抽象的。让一个小学生、中学生或本科生学习,他们都有各自学习的内容。而一个抽象概念的学生,他却不知道该学些什么。
这时,我们必须要对玩家类或学生类作一些限制了。由于玩家类和学生类直接实例化而创建的对象都是抽象而没有意义的,所以我们希望玩家类和学生类只能用于被继承,而不能用于直接创建对象。在C++中,我们可以把只能用于被继承而不能直接创建对象的类设置为抽象类(Abstract Class)。
之所以要存在抽象类,最主要是因为它具有不确定因素。我们把那些类中的确存在,但是在父类中无法确定具体实现的成员函数称为纯虚函数。纯虚函数是一种特殊的虚函数,它只有声明,没有具体的定义。抽象类中至少存在一个纯虚函数;存在纯虚函数的类一定是抽象类。存在纯虚函数是成为抽象类的充要条件。
那么我们该如何定义一个纯虚函数呢?纯虚函数的声明有着特殊的语法格式:
virtual 返回值类型成员函数名(参数表)=0;
请注意,纯虚函数应该只有声明,没有具体的定义,即使给出了纯虚函数的定义也会被编译器忽略。下面我们就修改一下程序17.7.1,将学生类变成一个抽象类:(程序17.9)
//student.h
#include <iostream>
using namespace std;
class student//因为存在纯虚函数study,student类自动变成了抽象类
{
public:
student(char *n,int a,int h,int w);
student();
void set(char *n,int a,int h,int w);
char * sname();
int sage();
int sheight();
int sweight();
virtual void study()=0;//声明study为纯虚函数
protected:
char name[10];
int age;
int height;
int weight;
};
char * student::sname()
{
return name;
}
int student::sage()
{
return age;
}
int student::sheight()
{
return height;
}
int student::sweight()
{
return weight;
}
void student::set(char *n,int a,int h,int w)
{
int i;
for (i=0;n[i]!='\0';i++)
{
name[i]=n[i];
}
name[i]='\0';
age=a;
height=h;
weight=w;
return;
}
student::student(char *n,int a,int h,int w)
{
cout <<"Constructing a student with parameter..." <<endl;
set(n,a,h,w);
}
student::student()
{
cout <<"Constructing a student without parameter..." <<endl;
}
//undergraduate.h和pupil.h同程序17.7.1
//main.cpp
#include <iostream>
#include "undergraduate.h"
#include "pupil.h"
using namespace std;
int main()
{
Undergraduate s1;
/*student s2;//此时创建学生对象将会出现编译错误*/
Pupil s3;
student *sp=&s1;
s1.set("Tom",21,178,60);
sp->study();
sp=&s3;
s3.set("Mike",8,148,45);
sp->study();
return 0;
}
运行结果:
Constructing a student without parameter...
Constructing a student without parameter...
学习高等数学和大学英语。
学习语数外。
我们看到,设置了纯虚函数之后并不影响多态的实现,但是却将父类变成了抽象类,限制了父类对象的创建。有了抽象类之后,就不会再出现不确定职业的玩家、不确定身份的学生了。