Google 开源项目风格指南阅读笔记(C++版)
虽说是编程风格指南,可是干货也不少,非常多C++的有用技术在里面。
头文件
通常每一个.cpp文件都相应一个.h文件;#define保护
全部头文件都应该使用#define防止头文件被多重包括,为保证唯一性,头文件的命名应该根据所在项目源代码树的全部路径。
能用前置声明的地方尽量不用#include
当一个头文件被包括的同一时候也引入了新的依赖,一旦该头文件被改动,代码就会被又一次编译,假设这个头文件又包括了其它头文件,这些文件的不论什么改变都将导致全部包括该头文件的代码被又一次编译。
假设头文件里用到类File,但不须要訪问File类的声明,头文件仅仅须要前置声明class File,而无需#include。
有时,使用指针成员替代对象成员是明智之举,然后这会减少代码可读性及效率。
内联函数
仅仅有当函数仅仅有10行甚至更少的时候才将其定义为内联函数,性能关键的函数,建议内联,不能包括switch语句。
复杂的内联函数的定义,应放在后缀名为 inl.h 的头文件里。
定义函数,參数顺序依次为:输入參数->输出參数,输入參数一般传值或者传const引用,输出參数则是非const指针。
#include的路径和顺序
使用标准的头文件包括顺序可增强可读性,避免隐藏依赖。顺序:C库,C++库,其它库.h,本项目.h.
包括文件的次序除了美观之外,最重要的就是减少隐藏依赖,使每一个头文件在“最须要编译的地方编译”。
作用域
鼓舞在.cpp文件里使用匿名名字控件,使用具名的名字空间时,其名称可基于项目名或相对路径,不要使用usingkeyword。
命名空间将全局作用域细分为独立的,具名作用域可有效防止全局作用域的命名冲突。
用命名空间把文件包括,gflags的声明和定义,以及类的前置声明以外的整个文件封装起来,以差别其它命名控件。
最好不要使用usingkeyword,以保证名字空间下的全部名称都能够正常使用。
在.cpp和.h的函数,方法和类中能够使用usingkeyword。
嵌套类
当共同拥有嵌套类作为接口的一部分时,尽管能够直接将他们保持在全局作用域中,但将潜逃类的声明置于命名空间内是更好的选择。
不要将嵌套类定义成公有,除非它们是接口的部分,比方嵌套类含有某些方法的一组选项。
非成员函数,静态成员函数和全局函数
使用静态成员函数或名字空间内的非成员函数,尽量不要用全裸的全局函数,假设必须定义非成员函数,又仅仅是在.cc文件里使用它,能够用匿名名字空间或static链接keyword,限定其作用域。
局部变量
将函数变量尽可能置于小的作用域内,并在变量声明时进行初始化。在循环中放置一个对象,则每次进入都要构造,离开都要析构。
静态和全局变量
禁止使用class类型的静态或全局变量,它们会导致非常难发现的bug和不确定的构造和析构函数调用顺序。
永远不要使用函数返回值初始化静态变量;不要在多线程代码中使用非const的静态变量。
作用域的使用除了考虑名称污染,可读性之外,主要是为了减少耦合,提高编译/运行效率。一般不要重载运算符,缺点是会混淆视听,难以调试。假设须要的话,能够定义相似Equals(), CopyFrom()等函数。
将全部数据成员声明为private,并根据须要提供相应的存取函数,一般在头文件里存取函数定义成inline。
类的訪问控制区段的声明顺序为public->protected->private.每一个区段的声明顺序:typedefs和枚举->常量->构造函数->析构函数->成员函数->数据成员。
函数尽量短小,紧凑,功能单一。
假设函数超过40行,能够考虑能不能在不影响程序结构的前提下进行切割。
尽量避免使用智能指针,使用时尽量局部化,安全第一。
假设一定要用智能指针,scoped-ptr全然能够胜任,仅仅在非常特定的情况下使用shared-ptr,不论什么时候都不要用auto_ptr;
其它C++特性
全部按引用传值的參数必须加上const。
输入參数是传值或者const引用,输出參数用指针。
仅在输入參数类型不同,功能同样时使用重载函数,不要用函数重载模拟缺省函数參数。
规定全部參数必须明白指定,迫使程序猿理解API和各參数值的意义,避免在不深入理解函数的情况下使用。
不要使用变长数组和alloc(),建议使用安全的分配器。
友元扩大了类的封装边界,某些情况下,相对域将类成员声明为public,使用友元是更好的选择,尤其是假设仅仅同意还有一个类訪问该类的私有成员时。
隐藏,覆盖和重载
隐藏 - 在基类中的某些函数,假设没有virtualkeywordkeyword,和其基类中的函数名一样,那么在子类中,基类的全部同名函数将被隐藏。
覆盖(override) - 派生类的虚函数覆盖了基类的同名具參数同样的函数,要一模一样,指的是函数名,參数,返回类型。
同样的函数名的函数,在基类和派生类中的关系仅仅能是覆盖或者隐藏。
重载 - 必须在一个域中,函数名称同样,可是函数參数不同。
除非单元測试,否则不要使用RTTI,假设发祥自己不得不写些行为逻辑取决于对象类型的代码,考虑换一种方式推断对象类型。
类型转换不要使用c风格类型转换,而应该使用C++风格。
1.static_cast特换c风格值转换,或某个类指针明白向上转换为父级指针;
2.const_cast去掉const属性;
3.reinterpret_cast指针类型和整数类型或其它指针之间进行不安全的相互转换;
4.測试代码之外不要用dynamic_cast.
不要使用流,除非是日志接口须要,使用printf之类的取代,使用流还有非常多利弊,但代码一致性胜过一切。
对于迭代器和其它模板对象,使用前缀形式(++i)的自增/自减运算符。
常量命名在名称前加k。
在不论什么可能的情况下使用const,类函数加上const表明该类不会改动成员变量的状态。
假设数据成员在对象构造之后再也不会发生变化,将其定义为const。
使用断言来指出变量为非负,而不是使用无符号型。
假设数据成员在对象构造之后再也不会发生变化,将其定义为const。
使用宏时要非常慎重,尽量以内联函数/枚举/常量取代。
宏意味着你和编译器看到的代码时不同的,可能会导致异常行为,尤其时由于其具有全局作用域。
不要在.h文件里定义宏
不要试图使用展开后会导致c++不稳定的宏,至少要附上文档说明行为。
文件凝视能够炫耀你的成就,也为了捅了篓子别人能够找你。
每一行代码字符不超过80个。
仅仅使用空格作为缩进符。
函数声明和实现处的全部形參,名称必须保持一致。
return表达式不要用圆括号包围。