介绍一个RPG游戏的时候,我们就说到不同职业的玩家在发动普通攻击和特殊攻击时,有着不同的效果。在编写程序的时候,我们并不知道用户会选择哪种职业的玩家,那么又该如何保证各种攻击效果和用户选择的玩家是对应的呢?
在使用继承的时候,子类必然是在父类的基础上有所改变。如果两者完全相同,这样的继承就失去了意义。同时,不同子类之间具体实现也是有所区别的,否则就出现了一个多余的类。不同的类的同名成员函数有着不同的表现形式,称为多态性。多态性是符合人的认知规律的,即称呼相同,所指不同。比如,学生类及其子类都有学习这个成员函数,但本科生、中学生、小学生的学习内容并不相同;玩家类的子类都有攻击这项技能,但剑士、弓箭手和魔法师的攻击方法不同。
多态性往往只有在使用对象指针或对象引用时才体现出来。编译器在编译程序的时候完全不知道对象指针可能会指向哪种对象(引用也是类似的情况),只有到程序运行了之后才能明确指针访问的成员函数是属于哪个类的。我们把C++的这种功能称为"滞后联编".多态性是面向对象的一个标志性特点,没有这个特点,就无法称为面向对象。
多态能够方便我们编写程序,可以让不同的类与它独特的成员函数一一对应。即使我们只是简单地"称呼",程序也会很明白我们的心思。那么,多态应该如何实现呢?
多态的实现
在C++中,我们把表现多态的一系列成员函数设置为虚函数。虚函数可能在编译阶段并没有被发现需要调用,但它还是整装待发,随时准备接受指针或引用的"召唤".设置虚函数的方法为:在成员函数的声明最前面加上保留字virtual.注意,不能把virtual加到成员函数的定义之前,否则会导致编译错误。
下面我们把各种学生的学习都设置为虚函数,了解如何实现多态:(程序17.7.1)
//student.h
#include
using namespace std;
class 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();//把学习设置为虚函数
protected:
char name ;
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…" < set(n,a,h,w);
}
student::student()
{
cout 《"Constructing a student without parameter…" < }
void student::study()//成员函数定义处没有virtual
{
cout 《"随便学些什么。" < return;
}
//undergraduate.h
#include "student.h"
class Undergraduate:public student
{
public:
double score();
void setGPA(double g);
bool isAdult();
virtual void study();//把学习设置为虚函数
protected:
double GPA;
};
double Undergraduate::score()
{
return GPA;
}
void Undergraduate::setGPA(double g)
{
GPA=g;
return;
}
bool Undergraduate::isAdult()
{
return age>=18 true:false;
}
void Undergraduate::study()//成员函数定义处没有virtual
{
cout 《"学习高等数学和大学英语。" < return;
}
//pupil.h
class Pupil:public student
{
public:
virtual void study();//把学习设置为虚函数
};
void Pupil::study()
{
cout 《"学习语数外。" < return;
}