Google 开源项目风格指南
里面包含五份(C++ 、Objective-C、Python 、JSON、Shell )中文版的风格指南。
如果你的类不需要拷贝 / 移动操作, 请显式地通过在 public 域中使用 = delete 或其他手段禁用之.
// MyClass is neither copyable nor movable.
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
结构体 VS. 类
仅当只有数据成员时使用 struct, 其它一概使用 class.
多重继承
真正需要用到多重实现继承的情况少之又少. 只在以下情况我们才允许多重继承: 最多只有一个基类是非抽象类; 其它基类都是以 Interface 为后缀的 纯接口类.
前置自增和自减
对简单数值 (非对象), 两种都无所谓. 对迭代器和模板类型, 使用前置自增 (自减).(++i)
不考虑返回值的话, 前置自增 (++i) 通常要比后置自增 (i++) 效率更高. 因为后置自增 (或自减) 需要对表达式的值 i 进行一次拷贝. 如果 i 是迭代器或其他非数值类型, 拷贝的代价是比较大的. 既然两种自增方式实现的功能一样, 为什么不总是使用前置自增呢?
文件名命名
文件名由基本名和后缀名构成,基本名由不大于8个的字母和数字组成,仅允许以字母开头,基本名应是有意义的名字,应与程序功能相一致。后缀名由不超过3个字符组成,常见后缀要求如下:
. name.h C ++header file
. name.cpp C++ source file
. name.inc Include file
. name.def Definition (Declaration) file
. name.cfg Compile declaration file
注意:严禁使用中文命名文件名
头文件内容
头文件中一般允许放下列内容:
• 宏定义
• 各种数据结构说明
• typedefs说明
• 外部函数说明
• 全局变量说明
头文件(*.h文件)的开始代码部分,一定要加上ifndef/define/ endif等预编译判断条件,防止头文件被重复包含;命名格式当是:< PROJECT>< PATH>< FILE>H
例如:项目foo中的头文件foo/src/bar/baz.h可按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
#endif // FOO_BAR_BAZ_H_
用 #include <filename.h> 格式来引用标准库的头文件(编译器将从标准库目录开始搜索);
用 #include “filename.h” 格式来引用自定义/非标准库的头文件(编译器将从用户的工作目录或者指定的路径开始搜索);
头文件名不应与标准函数库名相同;
头文件中只应包括多个文件都需要的内容。对于功能不同的内容应放在不同的头文件中;
一个头文件要有#define保护,统统包含它所需要的其他头文件,也不要求定义任何特别symbols;
尽可能地避免使用前置声明,使用#include包含需要的头文件即可;
只有当函数只有10行甚至更少时才将其定义为内联函数。谨慎对待析构函数,因为有隐含的成员和基类析构函数被调用。不要内联包含循环或switch语句的函数;
如果源文件的个数比较多(超过10个),应该根据软件需要/功能划分将源文件保存在不同的路径下,如下图所示:
建议:
1、头文件保存在include目录,程序文件保存在source或者src目录(可以根据需要设置为多级目录),资源文件保存在res目录,执行文件保存在bin目录,LIB库文件保存在lib目录,如果有配置文件可以保存在config目录;
2、对于某个程序文件所私有的头文件,没有必要公开“声明”。为了加强信息隐藏,这些私有的头文件可以存放于定义文件的子目录下,如” private/nameP.h”;
3、工程目录的各级子目录可以根据某种标准细分为各类子目录,每个子目录都应该包含一个readme文件。readme文件应该列举目录中包含的子文件及其主要作用说明;
4、如果有需要,可以增加其他目录如tmp等等,但建议基本结构不变;
5、在头文件中只存放“声明”而不存放“定义”;
6、#include中不能包括全路径,尽量采用相对路径。包含头文件的次序如下:
6.1、自相关头文件;
6.2、C系统文件;
6.3、C++系统文件;
6.4、其他库的.h文件;
6.5、本项目内.h文件。
可以插入空行以分割相关头文件/C库/C++库/其他库.h和本项目内的.h。
例外:平台特定(system-specific)代码需要条件编译(conditional includes),这些代码可以放到其它includes之后;
7、给自己的工程一个简短的编码代号如CSFM、CSM等,小组可以统一使用它做代码命名前缀
排版规则
1、在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。相对独立的程序块之间,变量说明之后必须加空行:
//空行
void function1(… …)
{
… …
//空行
while (condition)
{
statement1;
// 空行
if (condition)
{
statement2;
}
else
{
statement3;
}
// 空行
statement4;
}
… …
}
2、变量和运算符间要留有空隙,用一个空格符隔开,便于阅读。当然,特殊的单目运算符等除外,如“&”、“.”、“->”、“()”及作为指针运算符使用时的“*”。函数定义和调用中若出现多个参数,前一参数后应紧跟逗号运算符,并用一个空格符与后面参数隔开:
int i = 0; /*正确*/
int i=0 ; /*错误*/
a = b * c; /*正确*/
a=b*c; /*错误*/
if ((a == b) && (a != c)) /*正确*/
if((a==b)&&(a!=c)) /*错误*/
fuc(a, b, c, d) /*正确*/
fuc(a,b,c,d) /*错误*/
for (i = 0; i < 10; i++) /*正确*/
for(i=0;i<10;i++) /*错误*/
pPointer->a = pPointer->b * pPointer->c /*正确*/
pPointer -> a = pPointer -> b * pPointer -> c /*错误*/
int *pX = &i, y; /* 正确,此处y不会被误解为指针*/
int* pX = & i, y; /* 错误 */
3、一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释:
//如下例子不符合规范
rect.length = 0; rect.width = 0;