这个方法主张 virtual
函数应该几乎总是 private
。这个流派认为,较好的设计是保留 healthValue
为 public
成员函数,但让它成为 non-virtual
,并调用一个 private virtual
函数进行实际工作
class GameCharacter{ public: int healthValue() const{ // derived classes 不重新定义它 ... // 一些事前工作 int retVal = doHealthValue(); // 真正的工作 ... // 时候工作 return retVal; } ... private: virtual int doHealthValue() const{ // derived classes 可重新定义它 ... // 缺省算法,计算相关值 } };
class GameCharacter; // 前置声明 // 以下函数时计算健康指数的缺省算法 int defaultHealthCalc(const GameCharacter& gc); class GameCharacter{ public: typedef int (*HealthCalcFunc)(const GameCharacter&); // typedef了一个函数指针类型 explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) : healthFunc(hcf){} int healthValue() const { return healthFunc(*this); } ... private: HealthCalcFunc healthFunc; };
这种方式相对更常见
class EvilBadGuy:public GameCharacter{ public: explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc) : GameCharacter(hcf) {...} }; int loseHealthQuickly(const GameCharacter&); // 健康指数计算函数1 int loseHealthSlowly(const GameCharacter&); // 健康指数计算函数2 EvilBadGuy ebg1(loseHealthQuickly); // 相同类型的人物搭配 EvilBadGuy ebg2(loseHealthSlowly); // 不同的健康计算方式
通过 tr1:function
接触了之前要求必须是个函数,而不能是某种 “象函数的东西” (例如函数对象) 的限制
tr1::function: class GameCharacter; int defaultHealthCalc(const GameCharacter& gc); class GameCharacter{ public: // HealthCalcFunc 可以是任何 "可调用物" (callable entity), 可被调用并接受 // 任何兼容于 GameCharacter 之物,返回任何兼容于 int 的东西 typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc; explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) : healthFunc(hcf) {} int healthValue() const { return healthFunc(*this); } private: HealthCalcFunc healthFunc; }; 实例: short calcHealth(const GameCharacter&); // 健康计算函数 // 其返回类型是 non-int struct HealthCalculator{ // 为计算健康而设计的函数对象 int operator()(const GameCharacter&) const { ... } }; class GameLevel{ public: float health(const GameCharacter&) const; // 成员函数,用以计算健康 ... // 注意其 not-int 返回类型 }; class EvilBadGuy:pulic GameCharacter{ // 同前 ... }; class EyeCandyCharacter:public GameCharacter{ // 另一个任务类型 ... // 假设其构造函数与 }; // EvilBadGuy 同 EvilBadGuy ebg1(calcHealth); // 人物1,使用某个 // 函数计算 EyeCandyCharacter ecc1(HealthCalculator()); // 人物2,使用某个 // 函数对象计算 // Effective C++ P175 GameLevel currentLevel; ... EvilBadGuy ebg2( // 人物3,使用某个 std::str1::bind(&GameLevel::health, // 成员函数计算 currentLevel, _1) );
class GameCharacter; // 前置声明 class HealthCalcFunc{ public: ... virtual int calc(const GameCharacter& gc) const { ... } ... }; Health CalcFunc defaultHealthCalc; class GameCharacter{ public: explicit GameCharacter(HealthCalcFunc* phcf = &defaultHealthCalc) : pHealthCalc(phcf) {} int healthValue() const { return pHealthCalc->calc(*this); } ... private: HealthCalcFunc* pHealthClac; };