转贴【无责任书评:拳拳到肉 掷地铿锵的三本 OOP 绝佳小书】

wuwei 2000-06-15 02:56:00
无责任书评:拳拳到肉 掷地铿锵的三本 OOP 绝佳小书】

侯捷 jjhou@ccca.nctu.edu.tw
http://www.jjhou.com

本文将发表于 Run!PC 杂志 2000/07,并整理于 侯捷网站/散文 2000
----------------------------------------------------------------

拿破仑虽然是个矮个子,一生叱咤却俨然历史的巨人。
今天我要介绍的三本书,虽然轻薄短小有如拿破仑的身材,
在 C++/OOP 领域里,其份量与影响却也有着拿破仑般的辉煌灿烂。

说它们轻薄短小,是的,让数字说话:三本书合起来才
256+318+208=782 页,只比 C++ 语言知名教本 C++ Primer 3/e
一半篇幅再多一些而已,比起 C++ 语言权威著作
The C++ Programming Language 3/e 也才达到三分之二的页数份量。
逛书店时一个不留神,只怕你便遗漏了这些小书的存在。但如果你真
遗漏了它们的存在,实在是你的莫大损失。

就我个人的编程经验,以及我的教学经验(对象为业界工程师或
大学生),只要是 C++/OOP 设计思维与语言运用本身的问题,
非关 problem domain,百分之九十以上皆可在这三本书籍中找到
直接或间接的答案。这三本书是:

●Effective C++ 2/e : 50 Specific Ways to Improve Your Programs and Designs
●More Effective C++ : 35 New Ways to Improve Your Programs and Designs
●Exceptional C++ : 47 Engineering Puzzles, Programming Problems, and
Solutions
(注:前两本书亦有 CD 产品(HTML 格式),以两书合一的方式出售,
交叉索引甚为方便)

书名副标清楚告诉我们,这些书籍的特色就是以一个个的条款来
说明一些值得奉行或是必须避免的动作。以条款的方式进行,一方面
因为它们都不是 C++ 语言教本,而是更高层次的书籍,是给有语言基础
(最好还有实际工作经验)的人看的书,所以可以集中火力在特定主题上,
另一方面实乃因为条款型式可以强化主题,加深印象,提升查阅检索
的方便性与价值。

书中某些条款在 C++ 语言书籍里或多或少也都有提到 — 虽然解释
的深度可能不足。我举个例子,Effective C++ 的条款13说
「Initialization list 中的 members 初始化排列次序应该和其在 class 内
的宣告次序相同」,C++ Primer 3/e 的 p721~p722 对此有相同意义的描述。
再举个例子,Effective C++ 的条款14说
「总是让 base class 拥有 virtual destructor」,这在 C++ Primer 3/e
的 p933 亦有相同意义的描述。诸如此类,不胜枚举。但你是不是感觉,
那些金科玉律被淹没在语言百科型书籍的细节丛林之中!

每一条准则都简短、明确、容易记忆,可以确实提升你的软体效能。
每一条准则都是经验丰富的 C++ 程式员的心血结晶,告诉你哪些是
几乎总是需要奉行的动作,哪些是几乎肯定要避免的事情。
某些条款甚至到达 patterns 的水准(注)。

注:所谓 patterns,在指程式设计过程中,开发人员常需
面对并解决的某些问题,被有系统地整理出解法,谓之 patterns
(或译为「样式」)。Design Patterns 是此域中的经典书籍,
系统化地将可应用于众多领域之 23 个基本 patterns 加以
分类整理。书中所提的 patterns 名称,几乎成为物件导向
设计领域的标准辞汇。

以上三本小书的功用不仅在提纲契领地点出重点,也在于对
每个主题有深刻的讨论。在这些书籍中,你会发现一些忠告,
告诉你应该做些什么,为什么如此;也告诉你不应该做些什么,
又为什么如此。基本而言当然 whys 比 whats 更重要,
这便是这些书籍最有价值的地方。至于从速食的角度来看,
检阅一系列准则,也比强记一或二本庞杂的教科书更轻松方便得多。

----------------------------------------------------------

fig1

【基本资料】
书名:Effective C++ 2/e : 50 Specific Ways to Improve Your Programs and
Designs
作者:Scott Meyers
出版:Addison Wesley, 0-201-92488-9, 1998
定价:US$ 37.95
页数:256

Scott Meyers 的这本书籍,成名已久,同时也是此类书籍的滥觞。
这本书在 1992 年便有了第一版,我手上的第一版是 1996/12 的
第 12 刷。刷次原不能代表什么,不过我在第二版的封底看到,
出版公司宣称第一版销售超过十万本(不含各种译本)。销售量
能否代表什么呢?销售量低或许不一定能代表什么,销售量高则
相当程度地表示受到读者的肯定。以此书诉求之技术层面而言,
这个销售量是惊人的。(当然要是比起大陆某 C 语言书籍销售
270 万本,以及某 Visual Basic 书籍销售破千万本,那是小巫
见大巫了)

只要是在 C++ 领域里打滚的程式员,马上便可以从 Meyers 整理
出来的 50 个条款看出此书的价值。如果你拿 C++ 来讨生活,
稍稍阅读几个条款的深度后,不掏腰包者几稀。有些条款涉及的语意
层面较低,用以对容易出错或混淆的数种程式写法提出警告。另有
一些条款涉及的层次比较高,如第六章中对于各种继承型式的讨论、
以及 classes 之间除了继承以外的其他关系的讨论。至于条款E45
「知道 C++ 编译器默默为我们完成和呼叫哪些函式」,以及
条款M24「了解 virtual functions、multiple inheritance、
virtual base classes、RTTI 所需的成本」,下涉物件模型与编译器层面,
相当深入。套用我过去在「C++ 的沉迷与爱恋」一文中所用的辞,
此书在高热和骤冷之间,在高阶和低阶之间焠炼、循环、震荡。

本书第一页列有它所获得的赞誉。对于读者,这是一份值得参考的资料,
我试着把它们译为中文,条列于下:

※我必须真心地赞美 Meyers 的书,…这本书在记忆体管理架构
等主题上给予读者卓越的引导,并对不同型式之 C++ 继承机制
有极佳的解释。
- New York Computerist

※在你开始着手第一个真正的 C++ 专案之前,你应该阅读本书;
在你获得一些实务经验之后,你应该再读一遍。
- comp.lang.c++

※本书有一个子标题「改善你的程式技术与设计思维的 50 个
有效作法 」。作者不只提供你撰写 C++ 码时应该遵循的明白
规则,也提供了深入的解释与范例。
- Sun Expert

※我慎重推荐 Effective C++ 给任何渴望在中高阶层面精通
C++ 的人。
- The C User's Journal

※在各种写给中高阶程式员看的 C++ 书籍中,这是我所见过
最棒的一本。作者以一系列短文叙述 C++ 程式员遭遇的常见
问题。…本书既有趣又有用,在程式设计书籍中诚属罕见。
- comp.lang.c++

※本书在取材范围和风味上类似另一本由 William Strunk
和 E.B. White 合着的小书 The Eements of Style;至少
二者在我的书架上距离不远。…这是一本十分谨慎而适度的
小书,有着清楚的目标,并且完成了它们。
- C++ Report

※这本书内含对 C++ 开发工作的许多实用忠告。
- DEC Professional

※C++ 程式员不只应该拥有这本书,而且应该确实运用这本书。
书中的文字极易拿来实际运用。交叉参考与索引的功夫做得很好。
- Computer Language

※这是一本 193 页的杰作。…我保证 50 个条款中必定有
某一些会攫取你的注意力并对你产生启蒙作用,你的谨慎
投资将获得回报。…这是一本文笔优越、真材实料的书籍,
目标瞄准重视流畅与效率的所有 C++ 程式员。
- Stan Kelley-Bootle, UNIX Review

※这本绝妙好书提供了 50 个招数,帮助我们把 C++ 运用得
更好。每一位 C++ 程式员桌上都应该有这一本书。…在
提升 C++ 程式设计的整体品质上, Scott Meyers 这份
珍贵的礼物或许比业内任何人士的贡献都大。』
-- Jesse Liberty, C++ Report



下面列出 Effective C++ 2/e 的各个条款(我试着译为中文),
一方面让这篇书评的实用性更高一些,一方面就让这些条款标题
直接彰显它们的价值吧。

第一章:改变旧有的 C 习惯
条款1:尽量以 const 和 inline 取代 #define
条款2:尽量以 <iostream> 取代 <stdio.h>
条款3:尽量以 new 和 delete 取代 malloc() 和 free()
条款4:尽量使用 C++ 风格的注解型式

第二章:记忆体管理(Memory Management)
条款5:使用相同型式的 new 和 delete
条款6:记得在 destructor 中以 delete 对付 pointer members
条款7:为记忆体不足的状况预做准备
条款8:撰写 operator new 和 operator delete 时应遵行公约
条款9:避免遮掩了 new 的正规型式
条款10:如果你写了一个 operator new,请对应也写一个 operator delete

第三章:建构式,解构式,和 Assignment 运算子
条款11:如果 classes 内动态配置有记忆体,请为此 class 宣告一个 copy
constructor
和一个 assignment 运算子
条款12:在 constructor 中尽量以 initialization 取代 assignment
条款13:Initialization list 中的 members 初始化排列次序应该和其在 class 内的
宣告
次序相同
条款14:总是让 base class 拥有 virtual destructor
条款15:令 operator= 传回「*this 的 reference」
条款16:在 operator= 中为所有的 data members 指派内容
条款17:在 operator= 中检查是否「自己派给自己」

第四章:类别与函式之设计和宣告
条款18:努力让介面完满且最小化
条款19:区分 member functions, non-member functions 和 friend functions 三者
条款20:避免将 data members 放在公开介面中
条款21:尽可能使用 const
条款22:尽量使用 pass-by-reference(传址),少用 pass-by-value(传值)
条款23:当你必须传回 object 时,不要尝试传回 reference
条款24:在函式多载化(function overloading)和参数预设化(parameter
defaulting)
之间,谨慎抉择
条款25:避免对指标型别和数值型别进行多载化
条款26:防卫潜伏的 ambiguity(模棱两可)状态
条款27:如果不想使用编译器暗自产生的 member functions,就应该明白拒绝它
条款28:尝试切割 global namespace(全域命名空间)

第五章:类别与函式之实作
条款29:避免传回内部资料的 handles
条款30:避免写出 member function,传回一个 non-const pointer 或 reference 并
以之
指向较低存取层级的 members
条款31:千万不要传回「函式内 local 物件的 reference」,或是「函式内以 new 获
得的
指标所指的物件」
条款32:尽可能延缓变数定义式的出现
条款33:明智地运用 inlining
条款34:将档案之间的编译依存关系(compilation dependencies)降至最低

第六章:继承机制与物件导向设计
条款35:确定你的 public inheritance 模塑出 "isa" 的关系
条款36:区分「介面继承(interface inheritance)」和「实作继承
(implementation
inheritance)」
条款37:绝对不要重新定义一个继承而来的非虚拟函式
条款38:绝对不要重新定义一个继承而来的预设参数值
条款39:避免在继承体系中做 cast down(向下转型)的动作
条款40:透过 layering(分层技术)来模塑 has-a 或 is-implemented-in-terms-of
的关

条款41:区分 inheritance 和 templates
条款42:明智地运用 private inheritance(私有继承)
条款43:明智地运用多重继承(multiple inheritance,MI)
条款44:说出你的意思并了解你所说的每一句话

第七章:杂项讨论(Miscellany)
条款45:知道 C++(编译器)默默为我们完成和呼叫哪些函式
条款46:宁愿编译和联结时出错,也不要执行时才错
条款47:使用 non-local static objects 之前先确定它已有初值
条款48:不要对编译器的警告讯息视如不见
条款49:尽量让自己熟悉 C++ 标准程式库
条款50:加强自己对 C++ 的了解

-------------------------------------------------------------------

fig2

【基本资料】
书名:More Effective C++ : 35 New Ways to Improve Your Programs and Designs
作者:Scott Meyers
出版:Addison Wesley, 0-201-63371-X, 1996
定价:未标示
页数:318

继 Effective C++ 之后,Scott Meyers 于 1996 推出这本
「续集」。条款变得比较少,页数倒是多了一些,原因是
这次选材比「第一集」更高阶,尤其是第五章。Meyers 将
此章命名为技术(Techniques),并明白告诉你,其中都是
一些 patterns,例如 virtual ctors、smart pointers、
reference counting、proxy classes,double dispatching…
等等。这一章的每个条款篇幅都在 15~30 页之谱,实在让人有
「山穷水尽疑无路,柳暗花明又一村」之叹。

虽然出版年代稍嫌久远,本书并没有第二版,原因是当其
出版之时(1996),C++ Standard 已经几乎定案,本书
即依当时的标准草案而写。其间与现今之 C++ 标准规格
几乎相同。可能变化的几个弹性之处,Meyers 也都有所
说明与提示。读者可以连结作者提供的网址,看看上下两集
的勘误与讨论(数量之多,令人惊恐。幸好多是技术讨论
或文字斟酌,并没有什么重大误失)。

本书第一页列有它所获得的赞誉。对于读者,这是一份值得参考
的资料,我试着把它们译为中文,条列于下:

※这是一本多方面发人深省的 C++ 书籍:不论在你偶尔用到的
语言特性上,或是在你自以为十分熟悉的语言特性上。只有深刻
了解 C++ 编译器如何解释你的码,你才有可能以 C++ 语言写出
稳健强固的软体。本书是协助你获得此等层级之了解过程中,
一份极具价值的资源。读过本书之后,我P觉像是浏览了 C++
程式大师所检阅过的码,并获得许多极具价值的洞见。
- Fred Wild, Vce President of Technology,
Advantage Software echnologies

※本书内含大量重要的技术,这些技术是撰写优良 C++ 程式所
不可或缺的。本书解释如何设计和实作这些观念,以及潜伏在
其他某些替代方案中的陷阱。本书亦含晚近加入之 C++ 特性的
详细说明。任何人如果想要好好地运用这些新特性,最好买一本
并且放在随手可得之处,以备查阅。
- Chrisopher J. Van Wyk, Professor
Mahematics and Computer Science, Drew University

※这是一本具备工业强度的最佳书籍。对于已经阅读过 Effetive C++
的人,这是完美的续集。
- Eric Nagler, ++ Instructor and Author,
Univesity of California Santa Cruz Extension

※More Effective C++ 是一本无微不至而且价值不扉的书籍,
是 Scott 第一本书 Effective C++ 的续集。我相信每一位
专业的 C++ 软体开发人员都应该读过并记忆 Effective C++
和 More Effective C++ 两本书内的各种招式,以及其中重要
(并且有时候不可思议)的语言面向。我强烈推荐这两本书给
软体开发人员、测试人员、管理人员…,每个人都可以从 Scott
专家级的知识与卓越的表达能力中获益。
- Steve Burkett, Software Consutant


以下列出 More Effective C++ 的各个条款(我试着译为中文),
一方面让这篇书评的实用性更高一些,一方面就让这些条款标题
直接彰显它们的价值吧。

第一章:基础议题(Basics)
条款1:仔细区别 pointers 和 references
条款2:最好使用 C++ 转型运算子
条款3:绝对不要以 polymorphically(多型)方式来处理阵列
条款4:非必要不使用 default constructor

第二章:运算子(Operators)
条款5:对自定的型别转换函式保持警觉
条款6:区别 increment/decrement 运算子的前序(prefix)和后序(postfix)型式
条款7:千万不要多载化 &&, and and , 和 , 运算子
条款8:了解各种不同意义的 new 和 delete

第三章:异常情况(Exceptions)
条款9:利用 destructors 避免遗失资源
条款10:在 constructors 内阻止资源的遗失(resource leaks)
条款11:禁止异常讯息(exceptions)流出 destructors 之外
条款12:了解「丢出一个 exception」与「传递一个参数」或「呼叫一个虚拟函式」之
间的
差异
条款13:以 by reference 方式捕捉 exceptions
条款14:明智运用 exception specifications
条款15:了解异常处理(exception handling)的成本

第四章:效率(Efficiency)
条款16:谨记 80-20 法则
条款17:考虑使用 lazy evaluation
条款18:分期摊还预期的计算成本
条款19:了解暂时性物件的来源
条款20:协助完成「传回值最佳化(RVO)」
条款21:利用多载化技术(overload)避免隐式型别转换
条款22:考虑以运算子的复合型式(op=)取代其独身型式(op)
条款23:考虑使用其他程式库
条款24:了解 virtual functions、multiple inheritance、virtual base classes、
runtime type identification 所需的成本

第五章:技术(Techniques,又称 Idioms 或 Pattern)
条款25:将 constructor 和 non-member functions 虚拟化
条款26:限制某个 class 所能产生的物件数量
条款27:要求(或禁止)物件产生于 heap 之中
条款28:Smart Pointers(精灵指标)
条款29:Reference counting(参用计数)
条款30:Proxy classes(替身类别、代理人类别)
条款31:让函式根据一个以上的物件型别来决定如何虚拟化

第六章:杂项讨论(Miscellany)
条款32:在未来时态下发展程式
条款33:将非尾端类别(non-leaf classes)设计为抽象类别(abstract classes)
条款34:如何在同一个程式中结合 C++ 和 C
条款35:让自己习惯使用标准的 C++ 语言

-------------------------------------------------------------------

fig3

【基本资料】
书名:Exceptional C++ : 47 Engineering Puzzles, Programming Problems, and
Solutions
作者:Herb Sutter
出版:Addison Wesley, 0-201-61562-2, 1999
定价:US$ 33.95
页数:206

相较于前两本威名远播的老大哥,这本小书不但资历浅,作者
也似乎不是那么有名。真的不那么有名吗?未必,这要
看你熟悉哪个领域,在哪个领域活动而定。本书内容源自极受
欢迎的 C++ 网际网路节目 Guru of the Week,作者
Herb Sutter 正是这个网路节目的创办者,同时也是
C++ Report 的专栏作家,以及网际网路讨论群
comp.lang.c++.moderated 的创始主持人。

本书的一个最大特色是,以实例进行的方式,告诉你如何
以标准 C++ 进行软体工程。书中所列的实例,有些是
棘手的 C++/OOP 疑难杂症,有些展示稳健强固且具扩充性的程式码。
只需数分钟时间,你便可以拿书中一些 C++ 设计问题和
实作问题来挑战自己并且获得乐趣(是的,每个问题都有一个难度评分)。

每一个实例,都可以测验你的观念正确与否。书中许多主题与
Effective C++ 和 More Effective C++ 的条款相互辉映,
一个实例之中可能隐含了 Meyers 两本书的数个条款的运用。
顺带一提,这本书有老大哥 Scott Meyers 写序推荐。

以下列出 Exceptional C++ 的各个条款(我试着译为中文),
Sutter 下标题的方式不像 Meyers 那么具有实用性。不过,
这些标题大略呈现了本书的方向,所以,还是让它们自我说明吧。

第一章:泛型程式设计与 C++ 标准程式库
条款1:Iterators(泛型指标)
条款2:无分大小写的字串 之一
条款3:无分大小写的字串 之二
条款4:将泛型容器(Generic Containers)的重用性扩张至最大 之一
条款5:将泛型容器(Generic Containers)的重用性扩张至最大 之二
条款6:暂时物件
条款7:使用标准程式库(再谈暂时物件)

第二章:Exception-Safety(异常情况下仍然安全)的主题与相关技术
条款8: 撰写 Exception-Safe 程式码 之一
条款9: 撰写 Exception-Safe 程式码 之二
条款10:撰写 Exception-Safe 程式码 之三
条款11:撰写 Exception-Safe 程式码 之四
条款12:撰写 Exception-Safe 程式码 之五
条款13:撰写 Exception-Safe 程式码 之六
条款14:撰写 Exception-Safe 程式码 之七
条款15:撰写 Exception-Safe 程式码 之八
条款16:撰写 Exception-Safe 程式码 之九
条款17:撰写 Exception-Safe 程式码 之十
条款18:程式码复杂度 之一
条款19:程式码复杂度 之二

第三章:Class 的设计与继承
条款20:Class 技术
条款21:改写(Overriding)虚拟函式
条款22:Classes 之间的关系 之一
条款23:Classes 之间的关系 之二
条款24:使用/禁用 继承(Inheritance)
条款25:物件导向程式设计

第四章:编译器防火墙(Firewalls)及 Pimpl Idiom
条款26:将编译时期的依存性最小化 之一
条款27:将编译时期的依存性最小化 之二
条款28:将编译时期的依存性最小化 之三
条款29:编译防火墙(Compilation Firewalls)
条款30:The "Fast Pimpl" Idiom

第五章:名称查询(Name Lookup)、命名空间(Namespaes)、介面准则(Interface
Principle)
条款31:名称查询与介面准则 之一
条款32:名称查询与介面准则 之二
条款33:名称查询与介面准则 之三
条款34:名称查询与介面准则 之四

第六章:记忆体管理
条款 35:记忆体管理 之一
条款 36:记忆体管理 之二
条款 37:auto_ptr

第七章:陷阱、易犯错误与反常作法
条款 38:物件识别(Object Identity)
条款 39:自动转换(Automatic Conversions)
条款 40:物件寿命(Object Lifetimes)之一
条款 41:物件寿命(Object Lifetimes)之二

第八章:杂项主题
条款 42:变数的初始化
条款 43:常数性的正确性(Const-Correctness)
条款 44:转型(Casts)
条款 45:真假值(bool)
条款 46:转呼叫(Forwarding)函式
条款 47:控制流程(Control Flow)


●结语

理论与实务的结合,是每一位资讯从业人员希望达到的目标。
过多的照本宣科,过少的实务经验(真正有价值的实务经验),
却是目前资讯相关书籍的普遍写照。

Effective C++,More Effective C++, 和 Exceptional C++,
这三本书不仅在实务面上提出极为宝贵的准则,并以
丰富而扎实的理论基础,深入解释每一条准则背后的来龙去脉。
可以相当程度地提升你的 C++ 程式技术与 OO 设计思维。

著名的语言专家 Benjamin Whorf 曾说:『语言可以塑造人类
思考的方式,并决定人类思考的内容』。使用 C++ 语言,
绝不仅只于使用 C++ 编译器(很多人确是如此 — 虽然他们不自觉);
重要的是运用隐含于语意之中的物件导向(Object Oriented)观念
与泛型(Genericity)观念,在软体设计阶段便创造出一个
有弹性、易修改、适用未来时态的架构。

对于物件导向领域的生手,这三本书可以给你一个震憾教育,
让你知道过去的写作是多么地不严谨、观念是多么地不成熟。
或许这套书会促使很多自以为是的读者谦卑地认知自我的不足,
并谦卑地终于知道什么是井蛙、河鱼和燕雀。
至于物件导向个中老手,是的,这三本书为你整理出多年打滚
所获的宝贵心得,佐以深度的学理探讨,必然让你有相见恨晚之叹。

-- the end





...全文
276 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
gun2 2000-06-16
  • 打赏
  • 举报
回复
漫骂与诽谤不是战斗。

不要做工具的奴隶。虽然,享受别人的成果有轻松的愉悦,但我也常常沉浸于尽乎畸形的物恋中,需要时常反省自己。
ad 2000-06-15
  • 打赏
  • 举报
回复
一点都不羡慕。较弱智的人,才特别喜欢这样的书。
true_hero 2000-06-15
  • 打赏
  • 举报
回复
我有第一本书的中文版,羡慕吧

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧