这本书的中文名叫做《C++编程剖析》,从中文名字中你很难发现这本书和《Exceptional C++》以及《More Exceptional C++》是同一个系列的书(萨特的《Exceptional》系列) 。这本书和前两本是一脉相承的,只是感觉作者的写作风格(或者是译者的翻译风格)和 前两本有略微的不同。三本书依次读下来会发现作者的写作风格越来越幽默。
这三本书是萨特的Guru of the Week
的打印版本,基本上的内容似乎都可以在 GOTW
上面找到,其中#1 - #30
基本上出现在《Exceptional C++》一书中,#31 - #62
出现
在《More Exceptional C++》一书中,剩余的大部分则出现在这本书里面。如果你对于原
文比较感兴趣可以通过上面的连接去找找看。
正如其名《EXceptional C++ Style》一书中花了大量的篇幅去讨论编码的风格问题,这也 难怪作者会在这本书之后去写一本《C++ Coding Standards》专门讨论C++的编程风格。此 外萨特还和C++语言之父在github上起草编写了 CppCoreGuidelines 。
这本书一共 40 个条款,我直接跳过了其中的9-10两条和26-27两条,不看前者是因为 export这个特性很多的编译器不支持,而且在新的标准中已经废弃;至于后面两条涉及的 是优化问题,作者的核心理念是对于优化专业知识非常的重要,但是我没有关于国际象棋 方面的专业知识。
函数重载
这本书没有专门的条款去说明重载决议方面的问题,但是看完只会留下最深的印象的估计
就是它了。重载决议发生在查找模板特化之前,所以如果你特化一个函数模板,它很可能
根本起不了任何的作用,因为它很可能在重载决议阶段就已经被PASS掉了。同样的问题在
new operator
中也存在,如果你为你的类重载了三种形式之一而不重载其他两种,那么
其他两种形式无法正常工作,因为在重载决议的时候,编译器只能找到你定制的那一个版
本的new operator
从而导致参数不匹配的问题而调用失败。
1 | class Widget { |
此外,对于同一个成员函数的重载版本,如果分属不同的访问权限,同样很可能会出现这 种尴尬的问题。
1 |
|
上面这段代码是没有办法通过编译的,因为重载决议发生在权限判断之前。而重载决议发
现2
是最合适的版本,而权限判定发现它没有权限访问,即使存在1
这样的可行版本,
它也依旧无法使用。
private 到底意味着什么
private 意味者名字的可访问性,但是并不意味着名字可见性。所以才会出现上面提到的
错误。当然这里还涉及到的另一位关键字是名字
,如果我们通过函数指针绕过名字的可
见性,private
的成员函数依旧是可以被外界调用的,详见我的另外一篇博文《C++中访
问私有成员的方法》的第三种方法。
异常说明符
不要使用异常说明符,在C++11中这东西被废弃了,这本书中详细的讨论了为什么它会被废 弃。主要的原因就是,理想很丰满,但是现实很骨感。
虚函数
第一次听到 NVI
是在《Effective C++》中,梅耶轻描淡写的说这是很多人推崇的一种
很有意思的观点,很显然萨特就是这样的人。
通过模板方法模式,固定类的接口,把定制内容封装在 private
下的虚函数中,同时也
可以做一些额外的检测操作。我第一次发现NVI
的强大是在看完《程序员修炼之道》的按合约编程
之后,而这种风格的编程目前似乎被很多人推崇。
如果想要达到更好的接口和实现的分离,可以使用PImpl
手法,或者进一步通过使用策略
模式达到更大的灵活性。
内存模型
四个层次,三种形式。
内存管理有四个层次
- 操作系统接口
- 编译器的默认运行时库
- 标准库和标准分配器
- 用户自定义的容器或用户自定义的分配器
new operator() 有三种形式
嗯,刚学C++那会儿只知道new operator
的最基本的形式,后来读《深度探索C++对象模
型》一书的时候发现有placement new operator
的存在。读完这本书才知道原来
nothrow new
是它的第三种形式。
内联
《More Exceptional C++》一书中已经对于内联做了讨论,本书对讨论进行拓展。总的来 说还是那句老话,内联是一种优化,而过早的优化是一件愚蠢的事情。
我觉得迟早会有一天 inline
关键字会像 register
关键字一样形同虚设。
宏
宏是封装的天敌,它无视作用域,无视类型,悄无声息,形同鬼魅。所以珍爱生命,远离 宏(真的,因为宏造成的BUG会一点点的耗尽你的生命)。
远离生僻特性,知道,但是当他们不存在
双字符,三字符之类的东西,大部分情况下成事不足败事有余,所以不要去动他们。
尽量把函数写成非成员非友元
第一次接受这个观点在《Effective C++》一书,而对它的进一步的认识则来自《
Exceptional C++》中关于接口规则的讨论,《Exceptional C++ Style》透侧的分析了
std::string
也就是 basic_string<char>
没有遵守这个建议而存在的问题。我开始
也不敢相信,臃肿的它会有103
个成员函数(现在估计是只多不少)。