coding style is not only for the company, but also for your self-coding style. it is really important.
1.1. 通用命名规则
函数命名、变量命名、文件命名要有描述性,少用缩写。
尽可能给有描述性的命名方式,别心疼空间,毕竟让代码易于新读者理解很重要。不要用只有项目开发者能理解的缩写,也不要通过砍掉几个字母来缩写单词。
1.2. 文件命名
文件名要全部小写,可以包含下划线 ( _ ) 或者连字符 (-)。按项目约定来. 如果并没有项目约定,下划线”_” 更好。
- 可接受的文件命名:
my_useful_class.cc
myusefulclass.cc
C++ 文件要以 .cc 结尾, 头文件以 .h 结尾。专门插入文本的文件则以 .inc 结尾(目前不太清楚在哪里见过了)。不要使用已经存在于 /usr/include 下的文件名 (即编译器搜索系统头文件的路径),如db.h.通常应尽量让文件名更加明确。http_server_logs.h 就比 logs.h 要好。在定义类的时候文件名一般成对出现,比如 foo_bar.h 和 foo_bar.cc,对应于类 FooBar,内联函数必须放在 .h 文件中。如果内联函数比较短,就直接放在 .h 中。
1.3. 类型命名
类型名称的每个单词首字母均大写,不包含下划线:MyExcitingClass,MyExcitingEnum [大写式的驼峰法]
所有类型命名 —— 类, 结构体, 类型定义 (typedef), 枚举(enum),union ——均使用相同约定.
- classes and structs
class UrlTable { …}
class UrlTableTester { …}
struct UrlTableProperties { …} - typedefs
typedef hash_map<UrlTableProperties *, string> PropertiesMap; - enums
enum UrlTableErrors { …}
1.4. 变量命名
变量名一律小写,单词之间用下划线连接。类的成员变量以下划线结尾,但结构体的不用。
- 普通变量命名
string table_name - 类数据成员命名:
不管是静态的还是非静态的,类数据成员都可以和普通变量一样, 但要接下划线。
class TableInfo {
... ...
private:
string table_name_;
string tablename_;
static Pool<TableInfo>* pool_;
};
- 结构体变量命名:
不管是静态的还是非静态的,结构体数据成员都可以和普通变量一样,不用像类那样接下划线:
struct UrlTableProperties {
string name;
int num_entries;
}
- 全局变量命名:
对全局变量没有特别要求,在程序中尽量少用就好, 但如果你要用, 可以用 g_ 或其它标志作为前缀.
1.5. 函数命名
常规函数使用大小写混合,函数名的每个单词首字母大写,没有下划线。[与类的使用规则相同]
- 函数命名:
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
取值和设值函数则要求与变量名匹配:my_exciting_member_variable(),set_my_exciting_member_variable()。大致就是在库文件中常见的set/get等函数功能。
1.6. 名字空间命名
名字空间(namespace)用小写字母命名,并基于项目名称和目录结构:google_awesome_project.
1.7. 枚举命名
枚举的命名应当和常量或宏 一致:kEnumName 或是 ENUM_NAME。单独的枚举值应该优先采用常量的命名方式,但宏方式的命名也可以接受。枚举名 UrlTableErrors(以及 AlternateUrlTableErrors) 是类型,所以要用大小写混合的方式。
enum UrlTableErrors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
OK = 0,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2,
};
1.8. 宏命名
常见的宏命名方式都是以全部大写字母的形式出现:MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
#define ROUND(x) ...
#define PI_ROUNDED 3.0
1.9 其他重要注意事项
- 头文件—头文件内部不写任何namespace的内容,防止命名空间污染
1、#define保护
所有头文件应使用#define防止文件被多重包含,命名格式应为 <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
2、尽量减少.h中的#include的数量。
如:头文件总用到类File,但不需要访问File的声明,则头文件中只需声明class File即可
3、函数内联
当函数小于等于10行时可将其定义为内联函数;
内联函数尽量不要包含循环或switch语句,得不偿失;
递归函数不要声明为内联函数;
4、函数参数顺序
建议:输入参数在前,输出参数在后;
5、包含文件的名称及次序
建议次序:C库、C++库、其他库的.h、项目内的.h;
如:google-swesome-project/src/foo/internal/fooserver.cc的包含顺序:
#include “foo/public/fooserver.h”
#include <sys/types.h>
#include <unistd.h>
#include <hash_map>
#include <vector>
#include “base/basictypes.h”
#include “foo/public/bar.h” - 作用域
1、命名空间
谨慎使用命名空间,防止命名空间污染;
建议:.cc文件中使用不具名命名空间,以避免运行时的命名错误;
2、嵌套类
不要将嵌套类定义为public;
3、非成员函数、静态成员函数和全局函数
使用命名空间中的非成员函数或静态成员函数,尽量不要使用全局函数;
4、局部变量
将函数变量尽可能置于最小作用域内,在声明变量时将其初始化;
5、全局变量
禁止class类型的全局变量; - C++类
1、构造函数的职责
构造函数只进行那些没有实际意义的初始化,尽量使用Init()方法几种初始化为有意义的数据;
2、默认构造函数
如果累中定义了成员变量,没有提供其他构造函数,你需要定义一个默认构造函数。
3、明确的构造函数
对单参数构造函数使用C++关键字explicit;
4、结构体和类
仅当只有数据时使用struct,其他一概使用class;
5、继承
如果使用继承的话,只使用公共继承;
6、多重继承
真正需要多重继承的时候非常少,只有当最多一个基类中含有实现,其他基类都是以Interface为后缀的纯接口类时才使用多重继承;
7、接口
纯接口:
1)只有纯虚函数和静态函数(析构函数除外);
2)没有非静态数据成员;
3)没有定义任何构造函数;
4)如果是子类,也只能继承满足上述条件并以Interface为后缀的类;
8、操作符重载
一般不要重载操作符,尤其是赋值操作(operator=)比较阴险,应避免重载
9、存取控制
将数据成员私有化,并提供相关存取函数;
10、声明次序
public在private之前,成员函数在数据成员前;
一般次序:
1)typedefs和enums;
2)常量;
3)构造函数;
4)析构函数;
5)成员函数,含静态成员函数;
6)数据成员,含静态数据成员;
宏DISALLOW_COPY_AND_ASSIGN置于private块之后,作为类的最后部分;
11、编写短小函数
倾向于选择短小、凝练的函数,函数尽量不要超过40行; - 智能指针和其他C++特性
1、智能指针
如果需要智能指针的话,scoped_ptr完全可以胜任,在STL容器中,只使用std::tr1::shared_ptr,任何情况下都不要使用auto_ptr;
其他C++特性
1、引用参数
按引用传递的参数必须加上const;
2、函数重载
尽在输入参数类型不用、功能相同时使用重载函数,不要使用函数重载模仿缺省函数参数;
3、缺省参数
禁止使用缺省函数;
4、变长数组和alloca
禁止使用变长数组和alloca();
5、友元
允许合理使用友元类及友元函数;
6、异常
不要使用C++异常;
7、运行时类型识别
禁止使用RTTI(运行时类型识别,Run-Time Type Information);
8、类型转换
使用static_cast<>()等C++的类型转换,不要使用int y = (int)x;
9、流
只在记录日志时使用流
10、前置自增和自减
对于迭代器和模板类型来说,要使用前置自增;
11、const的使用
建议在任何可以使用的情况下都要使用const;
12、整型
可以使用<stdint.h>中的精确宽度的整型,如int16_t;
13、64位下的可移植性
14、预处理宏
使用宏要谨慎,尽量以内联函数、枚举和常量代之;
15、0和NULL
整数用0,实数用0.0,指针用NULL,字符串用’\0’;
16、sizeof(sizeof)
尽可能用sizeof(var)代替sizeof(type);
17、Boost库
只使用Boost中被认可的库; - 命名约定
1、通用命名规则
函数名、变量名、文件名应具有描述性,不要过度缩写;
2、文件命名
文件名要全部小写,可以包含下划线_,按项目约定来;
3、类型命名
类型命名每个单词以大写字母开头,不包含下划线;
类型包括——类、结构体、typedef、枚举;
4、变量命名
变量名一律小写,单词间以下划线相连,类的成员变量以下划线结尾;
全局变量以g_为前缀;
5、常量命名
在名词前加k:kDayInAWeek;
6、函数命名
普通函数大小写混合,存取函数要求与变量名匹配:MyExcitingFunction()、set_my_exciting_member_variable();
7、命名空间
命名空间的名词是全小写,其命名基于项目名词和目录结构;
8、枚举命名
枚举值应全部大写,单词间以下划线相连;
9、宏命名
类似枚举命名一样全部大写、使用下划线;*