2015 August 08 编程规则
Bjarne Stroustrup 语录
致读者
在编程序时,你是在为你针对某个问题的解决方案中的思想建立起一种具体表示。让程序的结构尽可能地直接反映这些思想:
- 如果你能把“它”看成一个独立的概念,就把它做成一个类。
- 如果你能把“它”看成一个独立的实体,就把它做成某个类的一个对象。
- 如果两个类有共同的界面,将此界面做成一个抽象类。
- 如果两个类的实现有某些显著的共同东西,将这些共性做成一个基类。
- 如果一个类是一种对象的容器,将它做成一个模板。
- 如果一个函数实现对某容器的一个算法,将它做成为对一族容器可用的模板函数。
- 如果一组类、模板等相互之间有逻辑联系,将它们放进一个名字空间里。
在你定义一个并不是实现某个像矩阵或复数这样的数学对象的类时,或者定义一个低层的类型如链接表的时候:
- 不要使用全局数据(使用成员)。
- 不要使用全局函数。
- 不要使用公用数据成员。
- 不要使用友元,除非为了避免a或c。
- 不要在一个类里面放“类型域”(指那种为了说明一个类所存储数据的情况而放置的标志域) ;采用虚函数。
- 不要用内联函数(inline function),除非作为效果显著的优化。
C++ 概览
- 不用害怕,一切都会随着时间的推移而逐渐明朗起来。
- 你并不需要在知道了C++的所有细节之后才能写出好的C++程序。
- 请特别关注程序设计技术,而不是各种语言特征。
标准库概览
- 不要像重新发明车轮那样企图做每件事;去使用库。
- 不要相信奇迹;要理解你的库能做什么,它们如何做,它们做时需要多大的代价。
- 当你遇到一个选择时,应该优先选择标准库而不是其他的库。
- 不要认为标准库对于任何事情都是最理想的。
- 切记#include 你所用到的功能的头文件。
- 记住,标准库的功能定义在名字空间std之中。
- 请用string,而不是char*。
- 如果怀疑,就用一个检查区间范围的向量(例如Vec)。
- vector 、list和 map<key,value> 都比T[] 好。
- 如果向一个容器中添加一个元素,用push_back() 或 back_inserter()。
- 采用对vector的push_back(),而不是对数组的realloc()。
- 在main()中捕捉公共的异常。
类型和声明
- 保持较小的作用域。
- 不要在一个作用域和它外围的作用域里采用同样的名字。
- 在一个声明中只声明一个名字。
- 让常用的和局部的名字比较短,让不常用的和全局的名字比较长。
- 避免看起来类似的名字。
- 维持某种统一的命名风格。
- 仔细选择名字,反映其意义而不是反映实现方式。
- 如果所用的内部类型表示某种可能变化的值,请用typedef 为它定义一个有意义的名字。
- 用typedef为类型定义同义词,用枚举或类去定义新类型。
- 切记每个声明中都必须描述一个类型(没有“隐式的int”)。
- 避免有关字符数值的不必要假设。
- 避免有关整数大小的不必要假设。
- 避免有关浮点类型表示范围的不必要假设。
- 优先使用普通的int 而不是short int 或者long int。
- 优先使用double 而不是float 或者long double。
- 优先使用普通的 char 而不是 signed char或者 unsigned char。
- 避免做出有关对象大小的不必要假设。
- 避免无符号算术。
- 应该带着疑问去看待从signed 到unsigned ,或者从unsigned 到signed 的转换。
- 应该带着疑问去看待从浮点到整型的转换。
- 应该带着疑问去看待向较小类型的转换,如将int转换到char。
忠告
- 避免非平凡的指针算术。
- 当心,不要超出数组的界线去写。
- 尽量使用0而不是NULL。
- 尽量使用vector 和valarray ,而不是内部(C风格)的数组。
- 尽量使用string而不是以0结尾的char 数组。
- 尽量少用普通的引用参数。
- 避免 void*,除了在某些底层代码里。
- 避免在代码中使用非平凡的文字量(“神秘的数”)。相反,应该定义和使用各种符号常量。(这里应理解为避免使用无意义的立即数,而定义一些能够代表意义的常量,例如,用true而不要用1(C/C++)或-1(VB))