有一部分人总是主张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的使用

条款35:考虑virtual函数以外的其他选择的更多相关文章

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

    virtual函数的替代方案包括NVI手法及Strategy设计模式的多种手法.NVI手法自身是一个特殊形式的Template Method设计模式. 将机能从成员函数移到class外部函数,带来的一 ...

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

    游戏中的人物伤害值计算问题. (一)方法(1):一般来讲能够使用虚函数的方法: class GameCharacter { public: virtual int healthValue() cons ...

  3. 条款35:考虑virtual函数以外的其他选择(Consider alternative to virtual functions)

    NOTE: 1.virtual 函数的替代方案包括NVI手法及Strategy设计模式的多种形式.NVI手法自身是一个特殊形式的Template Method设计模式. 2.将机能从成员函数移到外部函 ...

  4. 读书笔记_Effective_C++_条款三十五:考虑virtual函数以外的其他选择

    举书上的例子,考虑一个virtual函数的应用实例: class GameCharacter { private: int BaseHealth; public: virtual int GetHea ...

  5. 考虑virtual函数以外的其它选择

    详情见<Effective C++>item35 1.使用non-virtual interface(NVI)手法,这是Template Method设计模式的一种特殊形式. 它以publ ...

  6. [EffectiveC++]item35:考虑virtual函数以外的其他选择

    本质上是说了:   Template Pattern & Strategy Pattern 详细见<C++设计模式 23种设计模式.pdf 55页> 宁可要组合 不要继承. ——— ...

  7. EC读书笔记系列之16:条款35、36、37、38、39、40

    条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...

  8. Effective C++ -----条款09:绝不在构造和析构过程中调用virtual函数

    在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层).

  9. 条款9:不要在构造和析构过程中调用virtual函数

    如下是一个股票交易的例子: class Transaction // 交易的基类 { public: Transaction(); ; // 用于记录交易日志 }; Transaction::Tran ...

随机推荐

  1. Facebook支持python的开源预测工具Prophet

    Facebook 宣布开源一款基于 Python 和 R 语言的数据预测工具――“Prophet”,即“先知”.取名倒是非常直白. Facebook 表示,Prophet 相比现有预测工具更加人性化, ...

  2. redis3.2.11单机多实例集群部署并测试连接情况

    配置准备: redis3.2.11安装配置规划 机器 192.168.169.135(本机虚拟机) 系统 Red Hat Enterprise Linux Server release 6.4 (Sa ...

  3. A+B和C (15)

    时间限制 1000 ms 内存限制 32768 KB 代码长度限制 100 KB 判断程序 Standard (来自 小小) 题目描述 给定区间[-2的31次方, 2的31次方]内的3个整数A.B和C ...

  4. 如何用好 Google 等搜索引擎

    1: 双引号短语搜索2: 减号减号前面必须是空格,减号后面没有空格,紧跟着需要排除的词例如:搜索 -引擎返回的则是包含“搜索”这个词,却不包含“引擎”这个词的结果3: 星号RE,通配符4: intit ...

  5. Excel 查找某一列中包含指定字符的单元格

    网上查找相关内容,个人感觉是另一种形式的过滤喽.有的说用FIND,有的用高级筛选.我查找时如下: 1.新拉一列,标注公式“=ISNUMBER(FIND("宣",B2))”,然后拉至 ...

  6. vs2015 安卓相关配置

    vs2015的安卓相关配置百度不到,园子里也没人写.还是我没搜索到? 看来只能靠自己的英(pin)语(yin)能力一点点解决了 安装2015这个过程没啥可说的.都安装就OK了. 重要的就是选择安卓程序 ...

  7. android studio的安装和卸载

    安装: (待补充) 卸载: (如何彻底卸载才能达到第二次安装不受第一次安装失败的影响呢?) 1.找到安装目录,运行卸载文件.(不用清注册表,这是和卸载mysql的不同,只要把相关的文件夹,文件清楚即可 ...

  8. imx6solo wm8960始终没有声音输出

    我尝试各种办法,wm8960始终不能得到声音输出.调试过程如下: 首先,打开电源使能脚: ret=gpio_request(SABRESD_CODEC_PWR_EN,"audio_pwr_e ...

  9. qt5.4.1的imx6编译

    2.到https://download.qt.io/archive/qt/5.4/5.4.1/single/下载源码包qt-everywhere-opensource-src-5.4.1.tar.gz ...

  10. Django基础知识MTV

    Django简介 Django是使用Python编写的一个开源Web框架.可以用它来快速搭建一个高性能的网站. Django也是一个MVC框架.但是在Django中,控制器接受用户输入的部分由框架自行 ...