Effective C++条款35:考虑virtual函数以外的其他选择

假设你正在写一个游戏,你打算为游戏内的人物设计一个继承体系。
人物被伤害会掉血,因此你提供了一个成员函数healthValue,返回一个整数,表示人物的健康程度.由于不同的人物可能用不同的方式计算它们的掉血情况,将healthValue声明为virtual是显而易见的做法:

class GameCharacter
{
public:
	virtual int healthValue()const;
};

由于这个设计如此明显,从某个角度来说却成为了它的缺点,因为你可能没有认真考虑过其他替代方法。让我们来考虑其他的解法。

借由Non-Virtual Interface手法实现Template Method模式

这个设计的思路是:virtual函数应该总是private的,较好的设计是保留healthValuepublic成员函数,但让它成为非虚函数,并调用一个私有虚函数进行实际工作.
比如:

class GameCharacter
{
public:
	int healthValue()const
	{
		...
		int retVal = doHealthValue();
		...
		return retVal;
	}
	...
private:
	virtual int doHealthValue()const
	{
		...
	}
};

让客户通过public no-virtual成员函数简洁调用private virtual函数.
称为non-virtual interface(NVI)手法。是Template Method设计模式的一个独特的表现形式。
非虚函数称为虚函数的外覆器.
这个手法的优点是:你可以在外覆器中做一些事前工作和事后工作,事前工作比如锁定互斥器,验证函数先决条件、验证class约束条件等.事后工作包括互斥器解除锁定,验证函数的事后条件等等.

借由函数指针实现策略模式

还有一种设计主张是:人物健康指数的计算与人物类型无关。
这样的计算不需要人物这个成分,例如我们可能会要求每个人物的构造函数接受一个指针,指向一个健康计算函数,而我们可以调用该函数进行实际计算:

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);}
	...
private:
	HealthCalcFunc healthFunc;
};

这个做法的优点如下:
1.同一人物类型之不同实体可以有不同的健康计算函数
2.某个人物健康指数计算函数可以在运行期变更。

总结:

1.virtual函数的替代方案包括NVI手法以及策略设计模式的多种形式
2.将机能成从成员函数移动类外部函数,带来的一个缺点是:非成员函数无法访问类的非共有成员.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值