有一部分人总是主张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. sql获取该周的开始结束日期

    mssql函数 IF EXISTS ( SELECT 1 FROM sysobjects WHERE name = 'fn_GetWeekDate') DROP FUNCTION fn_GetWeek ...

  2. Java技术相关

    1.System.getProperty("user.dir") References:API

  3. Linux系统通过console口连接交换机

    一.安装minicomUbuntu安装:sudo apt-get install minicom.centos安装:yum install minicom二.配置minicomUbuntu输入:sud ...

  4. 【LeetCode】【动态规划】Edit Distance

    描述 Given two words word1 and word2, find the minimum number of operations required to convert word1  ...

  5. github资源下载速度慢的解决办法

    xx-net:https://github.com/XX-net/XX-Net

  6. Linux用户和用户组管理 用户配置和管理的相关文件

    用户信息文件 /etc/passwd 这个文件中保存的就是系统中所有的用户及其对应的用户主要信息. 文件格式 :  第1字段 第2字段 第3字段 第4字段 第5字段 第6字段 第7字段 用户名称 密码 ...

  7. TCP客户端和服务器间传输数据遇到的TypeError: a bytes-like object is required, not 'str'问题

    使用python实现python核心编程3第472页和474页的TCP时间戳服务器和客户端服务器间数据传输编程时遇到TypeError: a bytes-like object is required ...

  8. 常用模块-----configparser & subprocess

    configparser 模块 功能:操作模块类的文件,configparser类型文件的操作类似于字典,大多数用法和字典相同. 新建文件: import configparser cfg=confi ...

  9. codeforces 439C 模拟

    http://codeforces.com/problemset/problem/439/C 题意:给你n个数,分成k个非空集合,其中有p个集合的元素和为偶数,其余k-p个集合的元素和为奇数. 思路: ...

  10. jenkins tomcat

    tomcat增加用户配置: <role rolename="tomcat"/> <role rolename="role1"/> < ...