class GameCharacter { public: virtual int healthValue() const; // return character's health rating; ... // derived classes may redefine this }; 选择方案一: non-virtual interface (NVI) idiom(非虚拟接口惯用法) class GameCharacter { public: int healthValue() const // derived classes do not redefine { // this - see Item 36 ... // do "before" stuff - see below int retVal = doHealthValue(); // do the real work ... // do "after" stuff - see below return retVal; } ... private: virtual int doHealthValue() const // derived classes may redefine this { ... // default algorithm for calculating } // character's health }; 选择方案二: 函数指针 // function for the default health calculation algorithm 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); } ... private: HealthCalcFunc healthFunc; }; //使用:1. 相同角色类型的不同实例可以有不同的健康值计算函数。例如: class EvilBadGuy: public GameCharacter { public: explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc) : GameCharacter(hcf) { ... } ... }; int loseHealthQuickly(const GameCharacter&); // health calculation int loseHealthSlowly(const GameCharacter&); // funcs with different behavior EvilBadGuy ebg1(loseHealthQuickly); // same-type characters EvilBadGuy ebg2(loseHealthSlowly); // with different health-related behavior //2. 对于一个指定的角色健康值的计算函数可以在运行时改变。例如, GameCharacter可以提供一个 成员函数setHealthCalculator,它被允许代替当前的健康值计算函数。 选择方案三: tr1::function class GameCharacter; // as before int defaultHealthCalc(const GameCharacter& gc); // as before class GameCharacter { public: // HealthCalcFunc is any callable entity that can be called with // anything compatible with a GameCharacter and that returns anything // compatible with an int; see below for details 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&); // health calculation function; note non-int return type struct HealthCalculator { // class for health int operator()(const GameCharacter&) const // calculation function { ... } // objects }; class GameLevel { public: float health(const GameCharacter&) const; // health calculation ... // mem function; note }; // non-int return type class EvilBadGuy: public GameCharacter { // as before ... }; class EyeCandyCharacter: public GameCharacter { // another character ... // type; assume same }; // constructor as EvilBadGuy EvilBadGuy ebg1(calcHealth); // character using a health calculation function EyeCandyCharacter ecc1(HealthCalculator()); // character using a // health calculation function object GameLevel currentLevel; ... EvilBadGuy ebg2( // character using a health calculation std::tr1::bind(&GameLevel::health, currentLevel, _1) // member function; see below for details ); 选择方案四: 经典的strategy模式 class GameCharacter; // forward declaration class HealthCalcFunc { public: ... virtual int calc(const GameCharacter& gc) const { ... } ... }; HealthCalcFunc defaultHealthCalc; class GameCharacter { public: explicit GameCharacter(HealthCalcFunc *phcf = &defaultHealthCalc) : pHealthCalc(phcf) {} int healthValue() const { return pHealthCalc->calc(*this);} ... private: HealthCalcFunc *pHealthCalc; };