Item 35 考虑虚函数的替代者

● NVI: Non-Virtual Interface

class GameCharacter { public: int healthValue() const // 1. 子类不能重定义 { ... // 2. preprocess int retVal = doHealthValue(); // 2. 真正的工作放到虚函数中 ... // 2. postprocess return retVal; } ... private: virtual int doHealthValue() const { // 3. 子类可重定义 ... } };

 

NVI的优点:用一个不能被子类重定义的函数,做一些预处理、后处理。比如:互斥锁、日志、验证约束条件,等等。

● 函数指针

class GameCharacter; int defaultHealthCalc(const GameCharacter& gc); // default algorithm class GameCharacter { public: typedef int (*HealthCalcFunc)(const GameCharacter&); explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) : healthFunc(hcf) {} int healthValue() const { return healthFunc(*this); } ... private: HealthCalcFunc healthFunc; };

 

优先:对象实例和派生类对象,可使用各种实现,也可在运行时随意改变。
缺点:函数只能访问类内部的公有成员。这是一种隐患:可能以后需要访问私有成员,那么只有弱化类的封装。比如,把函数声明为友元;为私有成员提供访问函数。

● tr1::function比上面的函数指针更灵活、限制更少:
1> 返回值不一定是int,与其兼容即可
2> 可以是function对象
3> 可以是类的成员函数

class GameCharacter; int defaultHealthCalc(const GameCharacter& gc); class GameCharacter { public: // 与上面的函数指针不同,该处使用了tr1::function 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&); // 没返回int,但与int兼容 struct HealthCalculator { // 函数对象 int operator()(const GameCharacter&) const { ... } }; class GameLevel { public: float health(const GameCharacter&) const; // 成员函数 ... }; class EvilBadGuy: public GameCharacter { ... }; class EyeCandyCharacter: public GameCharacter { ... }; EvilBadGuy ebg1(calcHealth); EyeCandyCharacter ecc1(HealthCalculator()); GameLevel currentLevel; ... EvilBadGuy ebg2(std::tr1::bind(&GameLevel::health, currentLevel, _1));

 

● Strategy模式
优点:只要熟悉这个模式,就可以随时添加新算法。

class GameCharacter; 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; };

你可能感兴趣的:(Item 35 考虑虚函数的替代者)