Monday, December 5, 2011

Google C++ 编码风格精简

  Google C++ 编码风格精简

头文件:

1.头文件防多重定义define格式:<PROJECT>_<PATH>_<FILE>_H_

2.能使用前置声明尽量不用头文件包含

3.只有当函数只有 10 行甚至更少时才将其定义为内联函数(注意虚函数,递归函数,以及使用了循环语句的函数)

4.复杂的内联函数的定义, 放在后缀名为 -inl.h 的头文件中

5.定义函数时,输入参数永远放在输出参数之前

6.项目内头文件应按照项目源代码目录树结构排列

7.example.cc包含头文件顺序:example.h,C系统文件,C++ 系统文件,其他库的h文件,本项目内h文件

作用域:

1.在.cc文件中, 允许甚至鼓励使用匿名名字空间;不要在h文件中使用匿名名字空间 

2.在.cc文件.h文件的函数, 方法或类中, 可以使用 "using"关键字 及 名字空间别名 

3.不要将嵌套类定义成公有, 除非它们是接口的一部分, 比如, 嵌套类含有某些方法的一组选项

4.使用静态成员函数或名字空间内的非成员函数, 尽量不要用裸的全局函数 

5.将函数变量尽可能置于最小作用域内, 并在变量声明时进行初始化

6.禁止使用 class 类型的静态或全局变量: 它们会导致很难发现的 bug 和不确定的构造和析构函数调用顺序

类:

1.构造函数中只进行那些没什么意义的初始化, 可能的话, 使用 Init() 方法集中初始化有意义的数据

2.如果一个类定义了若干成员变量又没有其它构造函数, 必须定义一个默认构造函数

3.对单个参数的构造函数使用 C++ 关键字 explicit(如果构造函数只有一个参数, 可看成是一种隐式转换)

4.仅在代码中需要拷贝一个类对象的时候使用拷贝构造函数; 大部分情况下都不需要, 此时应使用 DISALLOW_COPY_AND_ASSIGN

{

#define DISALLOW_COPY_AND_ASSIGN(TypeName) /

TypeName(const TypeName&); /

void operator=(const TypeName&)

}

5.仅当只有数据时使用 struct, 其它一概使用 class

6.使用组合常常比使用继承更合理. 如果使用继承的话, 定义为 public 继承

7.如果你的类有虚函数, 则析构函数也应该为虚函数

8.当重载一个虚函数, 在衍生类中把它明确的声明为 virtual

9.只在以下情况我们才允许多重继承: 最多只有一个基类是非抽象类; 其它基类都是以Interface为后缀的纯接口类

10.接口是指满足特定条件的类, 这些类以 Interface 为后缀 (不强制).

11.尽量不要重载运算符

12.数据成员在任何情况下都必须是私有的, 并根据需要提供相应的存取函数

13.在类中使用特定的声明顺序: public: 在 private: 之前, 成员函数在数据成员前

14.如果函数超过 40 行, 可以思索一下能不能在不影响程序结构的前提下对其进行分割

Google奇技:

1.尽量避免使用智能指针(任何情况下都不要使用 auto_ptr),使用时也尽量局部化

2.使用 cpplint.py 检查风格错误

C++特性:

1. 输入参数是值参或 const 引用, 输出参数为指针.

2.仅在输入参数类型不同, 功能相同时使用重载函数 (含构造函数)

3.不允许使用缺省函数参数

4.不允许使用变长数组和 alloca()

5.不要在 Google 的开源项目中使用异常(关于这一点google仅仅是为了自身方便=。=)

6.禁止使用RTTI

7.使用 C++ 的类型转换, 如 static_cast<>(). 不要使用 int y = (int)x 或 int y = int(x) 等转换方式

{

用 static_cast 替代 C 风格的值转换, 或某个类指针需要明确的向上转换为父类指针时

用 const_cast 去掉 const 限定符

用 reinterpret_cast 指针类型和整型或其它指针之间进行不安全的相互转换. 仅在你对所做一切了然于心时使用 dynamic_cast 测试代码以外不要使用. 除非是单元测试, 如果你需要在运行时确定类型信息, 说明有 设计缺陷

}

8.只在记录日志时使用流

9.对迭代器和模板类型, 使用前置自增 (自减).对简单数值 (非对象)无所谓

10.强烈建议你在任何可能的情况下都要使用 const

{

如果函数不会修改传入的引用或指针类型参数, 该参数应声明为 const.

尽可能将函数声明为 const. 访问函数应该总是 const. 其他不会修改任何数据成员, 未调用非 const 函数, 不会返回数据成员非 const 指针或引用的函数也应该声明成 const.

如果数据成员在对象构造之后不再发生变化, 可将其定义为 const.

}

11.C++ 内建整型中, 仅使用 int. 如果程序中需要不同大小的变量, 可以使用 <stdint.h> 中长度精确的整型, 如 int16_t

12.使用断言来指出变量为非负数, 而不是使用无符号型

13.代码应该对 64 位和 32 位系统友好(!!!)

14.使用宏时要非常谨慎, 尽量以内联函数, 枚举和常量代替之

{

不要在 .h 文件中定义宏

在马上要使用时才进行 #define, 使用后要立即 #undef

不要只是对已经存在的宏使用#undef,选择一个不会冲突的名称

不要试图使用展开后会导致 C++ 构造不稳定的宏, 不然也至少要附上文档说明其行为

}

15.整数用 0, 实数用 0.0, 指针用 NULL, 字符 (串) 用 '/0'

16.尽可能用 sizeof(varname) 代替 sizeof(type)

17.只使用 Boost 中被认可的库

命名约定:

1.函数命名, 变量命名, 文件命名应具备描述性; 不要过度缩写. 类型和变量应该是名词, 函数名可以用 “命令性” 动词

2.文件名要全部小写, 可以包含下划线 (_) 或连字符 (-). 按项目约定来.

3.类型名称的每个单词首字母均大写, 不包含下划线: MyExcitingClass, MyExcitingEnum.

4.变量名一律小写, 单词之间用下划线连接. 类的成员变量以下划线结尾:my_local_variable,my_member_variable_

5.结构体的数据成员可以和普通变量一样, 不用像类那样接下划线

6.常量命名 在名称前加 k,接大写字母开头的单词

7.函数名的每个单词首字母大写, 没有下划线,取值和设值函数要与存取的变量名匹配.非常短小的内联函数名也可以用小写字母

8.名字空间用小写字母命名, 并基于项目名称和目录结构: google_awesome_project.

9.枚举的命名应当和常量一致: kEnumName.

代码注释:

1.使用行注释或块注释,统一就好

2.在每一个文件开头加入版权公告,然后是文件内容描述

{

版权;

许可版本:Apache2.0 BSD LGPL GPL;

作者;

文件内容

}

3.每个类的定义要附着类的功能和用法的注释

4.函数声明处注释描述函数功能,定义处描述函数实现

5.类数据成员应注释说明用途,是否可以接受NULL或-1等警戒值

6.全局变量注释说明含义和用途

7.复杂代码前要加注释;比较隐晦的代码后空两格加行尾注释

8.向函数传入整型,布尔值和指针时,注释说明含义,或使用常量让代码望文知意

9.临时,短期,或不够完美的解决方案使用TODO注释;格式//TODO(ID):Information

格式:

1.每一行长度不要超过80(路径,URL,头文件保护除外)

2.尽量不使用非ASCII字符,使用时必须使用UTF-8字符

3.只使用空格,每次缩进两个空格

4.函数声明:返回值和函数名在同一行,参数也尽量放在同一行

{

返回值总是和函数名在同一行;

左圆括号总是和函数名在同一行;

函数名和左圆括号间没有空格

圆括号与参数间没有空格;

左大括号总在最后一个参数同一行的末尾处 ;

右大括号总是单独位于函数最后一行;

右圆括号和左大括号间总是有一个空格;

函数声明和实现处的所有形参名称必须保持一致;

所有形参应尽可能对齐;

缺省缩进为2个空格;

换行后的参数保持4个空格的缩进;

}

5.如果函数声明成const,关键字const应与最后一个参数位于同一行 

6.如果有些参数没有用到, 在函数定义处将参数名注释起来

7.函数调用尽量放在同一行, 否则, 将实参封装在圆括号中

8.switch 语句可以使用大括号分段. 空循环体应使用 {} 或 continue. 

9.如果一个布尔表达式超过标准行宽断行方式要统一

10.return 表达式中不要用圆括号包围

11.预处理指令不要缩进, 从行首开始 

12.访问控制块的声明依次序是 public:, protected:, private:, 每次缩进 1 个空格

13.构造函数初始化列表放在同一行或按四格缩进并排几行

14.名字空间内容不增加缩进层次

15.永远不要在行尾添加没意义的留白

16.不在万不得已, 不要使用空行. 尤其是: 两个函数定义之间的空行不要超过 2 行, 函数体首尾不要留空行, 函数体中也不要随意添加空行

规则特例:

对于Windows程序员:

1.不要使用匈牙利命名法,使用 Google 命名约定, 包括对源文件使用 .cc 扩展名

2.尽量使用原有的 C++ 类型

3.使用 Microsoft Visual C++ 进行编译时, 将警告级别设置为 3 或更高, 并将所有 warnings 当作 errors 处理

4.不要使用 #pragma once; 而应该使用 Google 的头文件保护规则

5.除非万不得已, 不要使用任何非标准的扩展,

No comments:

Post a Comment