现在你工作在一个视频游戏上,你在游戏中为角色设计了一个 hierarchy(继承体系)。你的游戏中有着变化多端的恶劣环境,角色被伤害或者其它的健康状态降低的情况并不罕见。因此你决定提供一个 member function(成员函数)healthValue,它返回一个象征角色健康状况如何的整数。因为不同的角色计算健康值的方法可能不同,将 healthValue 声明为 virtual(虚拟)似乎是显而易见的设计选择:
class GameCharacter {
public:
virtual int healthValue() const; // return character's health rating;
... // derived classes may redefine this
};
这确实是一个显而易见的设计选择,而在某种意义上,这是它的缺点。因为这样的设计过于显而易见,你可能不会对它的其它可选方法给予足够的关注。为了帮助你脱离 object-oriented design(面向对象设计)的习惯性道路,我们来考虑一些处理这个问题的其它方法。
我们是在用 virtual functions(虚拟函数)来计算每一个角色的健康值。一个更引人注目的设计主张认为计算一个角色的健康值不依赖于角色的类型——这样的计算根本不需要成为角色的一部分。例如,我们可能需要为每一个角色的 constructor(构造函数)传递一个指向健康值计算函数的指针,而我们可以调用这个函数进行实际的计算:
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
typedef int (*HealthCalcFunc)(const GameCharacter&);
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const{
return healthFunc(*this);
}
//protected:
int a ;
private:
HealthCalcFunc healthFunc;
};
class EvilBadGuy : public GameCharacter {
public:
explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc)
: GameCharacter(hcf)
{}
};
int loseHealthQuickly(const GameCharacter& gc) {
cout << gc.a << endl;
}
int loseHealthSlowly(const GameCharacter&) {
cout << "loseHealthSlowly\n";
}
int main(){
EvilBadGuy ebg1(loseHealthQuickly);
EvilBadGuy ebg2(loseHealthSlowly);
ebg1.healthValue();
ebg2.healthValue();
return 0;
}
在这个办法中,健康值的计算已经不再是GameCharacter继承体系的一个成员函数的事实了,意味着它不在拥有访问它所计算的那个对象内部构建的特权。意味着这个计算只能调用这个对象的公有成员来计算,如果需要访问别的权限的变量,就需要加一些辅助手段了,比如友元等。