有一部分人总是主张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. 印象笔记Mac端快捷键

  2. mysql数据库补充知识7 索引原理与慢查询优化

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

  3. "export" in SHELL

    在shell中,若某一变量需要在随后的子程序中运行,则需要以 export 来使变量变成环境变量: export var export的用法总结: 1:一个shell中用export定义的变量,只对当 ...

  4. Personal Ubuntu

    @1:修改了打开主文件夹的快捷键 CTRL + ALT + R @2:增加了强制关闭程序的快捷键CTRL + ALT+ X,程序为~/lxw0109/ownAdmin/closeProgram.sh( ...

  5. 0607am抽象类&接口&析构方法&tostring&小知识点

    /*class ren{ public static $color;//静态 static function () { ren::$color; self::$color;//self只能写在类里面, ...

  6. 我的npm笔记

    本文记录一些npm的使用技巧,主要包括自己常用的命令,做个备忘. NPM 是什么? NPM是NodeJS的包管理工具,现在已经进一步发展,致力于为很多其他平台提供包管理工具,其核心思想就是让包的安装更 ...

  7. springboot-vue项目后台2

    Main.java package com.hcxy.car; import org.springframework.boot.SpringApplication; import com.hcxy.c ...

  8. Linux Shell基础 位置参数变量、预定义变量

    位置参数变量 在 Linux 的命令行中,当一条命令或脚本执行时,后面可以跟多个参数,我们使用位置参数变量来表示这些参数.其中,$0 代表命令行本身,$1 代表第 1 个参数,$2 代表第 2 个参数 ...

  9. 最新版express使用时的变化

    原文:http://www.unfish.net/archives/772-20131207.html 很幸运地找到这篇文章,里面的内容讲的非常的细,对于开始着手搭建项目的我来说特别有用.但文中的部分 ...

  10. 基于SSM的单点登陆03

    TbUser.java和TbUserExample.java,TbUserMapper.java,TbUserMapper.xml由mybatis框架生成. generatorConfig.xml & ...