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

有一部分人总是主张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来进行指定(这样降低了耦合)
 1 class GameCharacter;
 2 int defaultHealthCalc(const GameCharacter & gc);
 3 class GameCharacter{
 4 public:
 5     typedef std::function<int (const GameCharacter & )>  HealCalcFunc
 6     explicit GameCharacter(HealCalcFunc hcf = defaultHealthCalc)
 7     :healthFunc(hcf){}
 8     int healthValue() const
 9     {return healthFunc(* this); }
10     ...
11 private:
12     HealCalcFunc healthFunc;
13 };

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

 1 short clacHealth(const GameCharacter &);
 2 //或者是一个函数对象
 3 struct HealCalculater{
 4 public:
 5     float operator()(const GameCharacters & gc) const ;
 6 };
 7 //或者是一个成员函数。
 8 class GameLevel{
 9 public:
10     float Health(const GameCharacters)const;
11 };
12 GameCharacters character1(clacHealth);
13 GameCharacters character2(HealCalculater());
14 GameLevel levelObj;
15 GameCharacters character3(std::bind(&GameLevel::health, levelObj, _1));//不记得这样写对不对,待查
上面这些例子都可以正确通过切运行,这说明这种方式给我们带来的弹性是很大的。
 
不仅如此,这种方式在延伸一下就可以设计出来典型的策略模式:
 1 class HealCalculater;
 2 class GameCharacter;
 3 int defaultHealthCalc(const GameCharacter & gc);
 4 class GameCharacter{
 5 public:
 6     typedef std::function<int (const GameCharacter & )>  HealCalcFunc
 7     explicit GameCharacter(HealCalcFunc hcf = defaultHealthCalc)
 8     :healthFunc(hcf){}
 9     int healthValue() const
10     {return healthFunc(* this); }
11     ...
12 private:
13     HealCalcFunc * phealthFunc;
14 };
15 HealCalculater{
16 public : 
17     virtual int calc(const GameCharacter & gc)const
18     {}    //也可以只声明一个接口
19 }
小结:
    virtual函数的替代方案包括nv1手法以及strategy设计模式等多种形式
    将机能从成员函数移动到class外部函数,带来的缺点是非成员函数无法访问class的non-public成员
    注意function已经bind的使用

 

posted @ 2015-10-18 16:55  eversliver  阅读(426)  评论(0编辑  收藏  举报