Effective C++ Item 35 Consider alternatives to virtual functions
考虑你正在为游戏人物设计一个继承体系, 人物有一个函数叫做 healthValue, 他会返回一个整数, 表示人物的健康程度. 由于不同的人物拥有不同的方式计算他们的健康指数, 将 healthValue 声明成一个 virtual 似乎是再合适不过的了
class GameCharacter {
public:
virtual int healthValue() const;
...
};
那么, 它还有没有其他的实现形式呢?
1. 藉由 Non-Virtual Interface 手法实现 Template Method 模式
class GameCharacter {
public:
virtual int healthValue() const {
...
int retVal = doHealthValue();
...
return retVal;
} private:
virtual int doHealthValue() {
...
}
};
NVI 手法的一个隐身优点是上述代码注释"做一些事前工作", "做一些事后工作". 这意味着 wrapper 确保得以在一个 virtual 函数被调用之前设置好适合场景, 并在调用之后清理场景.
另外, doHealthValue 没必要是 private
2. 藉由 Function Pointer 实现 Strategy 模式
具体实现是
class GameCharacter {
public:
typedef int (*HealthCalcFunc)(const GameCharacter&); explicit GameCharacter(HealthCalcFunc hcf) {
healthFunc = hcf;
} int healthValue() const {
return healthFunc(*this);
}
...
private:
HealthCalcFunc healthFunc;
};
从上面的代码可以看出 内部策略函数的框架是 int (*pf) (const GameCharacter)
函数唯一的参数是 GameCharacter, 这意味着血量的计算通过 GC(GameCharacter) 的 public 借口即可完成计算, 不需要设计其 private 的部分. 而假如不得不引用 private 部分, 那么 "弱化封装" 是唯一的解法.
3. 藉由 tr1::function 完成 Strategy 模式
从 Java 转过来的程序员可能对函数指针这个东西会产生莫名的恐惧, 额, 我就是其中之一, 能不能将策略模式的核心转换成类似对象的东西呢? 答案是肯定的, 这也构成了第(3), (4) 小节的题目
class GameCharacter {
public:
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
... // 其他部分完全与函数指针方法兼容
}
tr1::function 充当了一个泛化的函数, 其依然能够接受函数指针, 能够接受函数对象, 甚至使用 bind
short calcHealth(const GameCharacter&);
struct HealtheCalculator {
int operator()(const GameCharacter&) const {
...
}
}; class GameLevel {
public:
float health(const GameCharacter&) const;
...
}; class EvilBadGuy:public GameCharacter {...};
class EyeCandyCharater: public GameCharacter{...}; EvilBadGuy ebg1(calcHealth); // 接受一个函数
EyeCandyCharater ecc1(HealtheCalculator());// 接受函数对象
GameLevel currentLevel;
EvilBadGuy( // 接受某一个成员函数
std::tr1::bind(&GameLevel::health, currentLevel, _1)
);
GameLevel::health 函数有两个参数, bind 则指定 currentLevel 作为调用 health 的对象
4. 古典 Strategy 模式
正如上面 策略模式的图解一样, 古典策略模式会将健康计算函数成为一个分离继承体系中的 virtual 函数
Effective C++ Item 35 Consider alternatives to virtual functions的更多相关文章
- 读书笔记 effective c++ Item 35 考虑虚函数的替代者
1. 突破思维——不要将思维限定在面向对象方法上 你正在制作一个视频游戏,你正在为游戏中的人物设计一个类继承体系.你的游戏处在农耕时代,人类很容易受伤或者说健康度降低.因此你决定为其提供一个成员函数, ...
- Effective JavaScript Item 35 使用闭包来保存私有数据
本系列作为EffectiveJavaScript的读书笔记. JavaScript的对象系统从其语法上而言并不鼓舞使用信息隐藏(Information Hiding).由于当使用诸如this.name ...
- 读书笔记 effective c++ Item 37 永远不要重新定义继承而来的函数默认参数值
从一开始就让我们简化这次的讨论.你有两类你能够继承的函数:虚函数和非虚函数.然而,重新定义一个非虚函数总是错误的(Item 36),所以我们可以安全的把这个条款的讨论限定在继承带默认参数值的虚函数上. ...
- 读书笔记 effective c++ Item 39 明智而谨慎的使用private继承
1. private 继承介绍 Item 32表明C++把public继承当作”is-a”关系来对待.考虑一个继承体系,一个类Student public 继承自类Person,如果一个函数的成功调用 ...
- 读书笔记 effective c++ Item 54 让你自己熟悉包括TR1在内的标准库
1. C++0x的历史渊源 C++标准——也就是定义语言的文档和程序库——在1998被批准.在2003年,一个小的“修复bug”版本被发布.然而标准委员会仍然在继续他们的工作,一个“2.0版本”的C+ ...
- Standard C++ Programming: Virtual Functions and Inlining
原文链接:http://www.drdobbs.com/cpp/standard-c-programming-virtual-functions/184403747 By Josée Lajoie a ...
- [CareerCup] 13.3 Virtual Functions 虚函数
13.3 How do virtual functions work in C++? 这道题问我们虚函数在C++中的工作原理.虚函数的工作机制主要依赖于虚表格vtable,即Virtual Table ...
- [C++] OOP - Virtual Functions and Abstract Base Classes
Ordinarily, if we do not use a function, we do not need to supply a definition of the function. Howe ...
- Effective C++ -----条款35:考虑virtual函数以外的其他选择
virtual函数的替代方案包括NVI手法及Strategy设计模式的多种手法.NVI手法自身是一个特殊形式的Template Method设计模式. 将机能从成员函数移到class外部函数,带来的一 ...
随机推荐
- 基于python的接口测试框架设计(三)接口测试的框架
基于python的接口测试框架设计(三)接口测试的框架 其实我这里用到的是unittest单元测试框架,,这个框架好就好在比较清楚,,setup terdown都可以处理一些初始化及完成后的工作 主要 ...
- Linux下安装Python3.6和第三方库
如果本机安装了python2,尽量不要管他,使用python3运行python脚本就好,因为可能有程序依赖目前的python2环境, 比如yum!!!!! 不要动现有的python2环境! 一.安装p ...
- 转载:[Mitbbs]FB的intern和准备的经历
今天中午刚收到f家的intern offer, 超级开心.在这个版块看了很多也收获很多. onsite前天晚上面就就对自己过了一定发个帖跟需要的人分享下自己的经历.论坛上帖 子看了很多,很多拿了FLA ...
- 一款基jquery超炫的动画导航菜单
今天给大家分享一款基jquery超炫的动画导航菜单.这款导航菜单,初始时页面中间一个按钮,单击按钮,菜单从左侧飞入页中.再次单击按钮,导航飞入左侧消息.动画效果很非常炫.一起看下效果图: 在线预览 ...
- Win10技巧:如何确定电脑是否适用Hyper-V虚拟机?
既然微软想要为Hyper-V的普及铺路,那么各种套路……配套措施当然也会一并跟上.比如想要看出电脑是否符合Hyper-V配置要求,有至少两种方式可以参考. 方法一:系统信息 这方法很简单,在Corta ...
- Java NIO使用及原理分析 (一)(转)
最近由于工作关系要做一些Java方面的开发,其中最重要的一块就是Java NIO(New I/O),尽管很早以前了解过一些,但并没有认真去看过它的实现原理,也没有机会在工作中使用,这次也好重新研究一下 ...
- hibernate不调用save也保存上了
List<Instrument> insts = instService.search(search); if (insts.size() == 1) { Instrument inst ...
- UC浏览器调试移动端网站
准备工作: UC浏览器开发版网址 UC浏览器开发者版下载地址 下载adb_tool 步骤: 1.将adb_tool解压,把里面的文件复制到 C:\Windows\SysWOW64 文件夹下面. 2.运 ...
- osql.exe 批处理sql 文件
.bat文件内容 "C:\Program Files\Microsoft SQL Server\110\Tools\Binn\osql.exe" -U sa -P sa -S 19 ...
- [HTML] 使用size和maxlength分别控制文本框宽度和输入字符数的限制
① size一般可以直观的看到,就是文本框的宽度,只能决定文本框的宽度,也就是可以看到的字符的个数. 如:size="5" 这意味着如果输入 我的国家是北京 那么只能看见 我 ...