您的位置:首页 > 其它

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

2015-10-18 16:55 393 查看
有一部分人总是主张virtual函数几乎总应该是private:例如下面这个例子,例子时候游戏,游戏里面的任务都拥有健康值这一属性:

class GameCharacter{
public:
int healthValue()const{
...
int retVal = doHealthValue();
...
return retVal;
}
private:
virtual int doHealthValue() const
{
}//上面的这个non-virtual函数实际上是virtual函数的一个外覆器
};


这里使用一个外覆器的好处是:了一使用外覆器在调用虚函数之前以及之后分别做一些特定的操作。例如锁定mutex或者是解锁mutex这种事。
上面这个可以称为Template Method模式的一种特例:

还有用function Pointer实现的strategy模式;假如healthValue的规则有一个内含的成员healthFunc来进行指定(这样降低了耦合)

class GameCharacter;
int defaultHealthCalc(const GameCharacter & gc);
class GameCharacter{
public:
typedef std::function<int (const GameCharacter & )>  HealCalcFunc
explicit GameCharacter(HealCalcFunc hcf = defaultHealthCalc)
:healthFunc(hcf){}
int healthValue() const
{return healthFunc(* this); }
...
private:
HealCalcFunc healthFunc;
};


实际上,这个typedef带来的弹性是很大的:

short clacHealth(const GameCharacter &);
//或者是一个函数对象
struct HealCalculater{
public:
float operator()(const GameCharacters & gc) const ;
};
//或者是一个成员函数。
class GameLevel{
public:
float Health(const GameCharacters)const;
};
GameCharacters character1(clacHealth);
GameCharacters character2(HealCalculater());
GameLevel levelObj;
GameCharacters character3(std::bind(&GameLevel::health, levelObj, _1));//不记得这样写对不对,待查


上面这些例子都可以正确通过切运行,这说明这种方式给我们带来的弹性是很大的。

不仅如此,这种方式在延伸一下就可以设计出来典型的策略模式:

class HealCalculater;
class GameCharacter;
int defaultHealthCalc(const GameCharacter & gc);
class GameCharacter{
public:
typedef std::function<int (const GameCharacter & )>  HealCalcFunc
explicit GameCharacter(HealCalcFunc hcf = defaultHealthCalc)
:healthFunc(hcf){}
int healthValue() const
{return healthFunc(* this); }
...
private:
HealCalcFunc * phealthFunc;
};
HealCalculater{
public :
virtual int calc(const GameCharacter & gc)const
{}    //也可以只声明一个接口
}


小结:
virtual函数的替代方案包括nv1手法以及strategy设计模式等多种形式
将机能从成员函数移动到class外部函数,带来的缺点是非成员函数无法访问class的non-public成员

注意function已经bind的使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: