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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值