一、头文件
1、除了单元测试、main之外每一个cpp文件都有对应的h文件
2、#define保护格式<PROJECT>_<PATH>_<FILE>_H_,例如proj/src/path/file.h采用#ifndef PROJ_PATH_FILE_H_
3、前置声明代替#include。a:成员变量声明为Foo *或Foo &;b:函数参数、返回值类型,静态数据成员的类型为类Foo的
4、-inl.h文件:复杂的内联函数定义在后缀名为-inl.h的头文件中。
5、函数参数顺序:输入参数在前,输出参数在后。
6、保函头文件顺序(例如在project/src/base/logging.cpp中):
#include "base/logging.h"(优先位置)
C系统文件
C++系统文件
其他库头文件
本项目内头文件
二、作用域
1、命名空间(不太熟):尽量不要使用using来污染命名空间
2、使用命名空间中的“非成员函数”、“静态函数”,而不是“全局函数”。.cpp文件中暂用的可以用“不具名命名空间”或者static关联(如static int foo(){...})。
3、禁止class类型全局变量(全局变量只能是内建类型),多线程中禁止非常数全局变量,禁止使用函数返回值初始化全局变量。类静态成员变量也被视作全局变量。
三、类
1、构造函数:只做没意义的动作,有意义的放到Init()方法中;要提供默认构造;将关键字 explicit 加到单参数极造函数前防止隐式转换。
2、不需要拷贝时应使用 DISALLOW_COPY_AND_ASSIGN。
// 禁止使用拷贝极造函数和赋值操作的宏
// 应在类的 private:中使用
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
class Foo {
public:
Foo(int f); ~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};
3、仅当只有数据时使用 struct,其它一概使用 class。
4、使用组合通常比使用继承(只用公共继承)更适宜。C++实践中,继承主要用于实现继承(implementation inheritance),子类继承父类的实现代码;接口继承(interface inheritance),子类仅继承父类的方法名称。
5、接口以Interface为后缀
6、尽量少重载操作符
7、存取控制。私有化成员变量foo_,定义取值函数foo()、赋值函数set_foo(),可内联
8、定义次序如下:public:、protected:、private:,如果那一块没有,直接忽略即可。每一块中,声明次序一般如下:
1) typedefs 和 enums;
2) 常量;
3) 构造函数;
4) 析构函数;
5) 成员函数,含静态成员函数;
6) 数据成员,含静态数据成员。
宏 DISALLOW_COPY_AND_ASSIGN 置亍 private:块最后,作为类的最后部分。
四、C++特性
1、智能指针用scoped_ptr。STL容器中使用shared_ptr。禁止使用auto_ptr
2、按引用传递的参数必须加上 const。事实上这是一个硬性约定:输入参数为值或常数引用,输出参数为指针;输入参数可以是常数指针,但不能使用非常数引用形参。
3、禁止使用缺省函数参数。禁止使用变长数组和alloca。
4、合理使用友元。可以将FooBuilder、单元测试类声明为Foo的友元。
5、不要使用C++异常。
6、禁止使用运行时类型识别(RTTI)(就是反射吧~)
7、类型转换用static_cast<>(), const_cast, reinterpref_cast, 不要用dynamic_cast。
8、尽量用printf()系列函数代替流,只在记录日志式使用流。
9、用++i/--i代替i++/i--。
10、能用const的时候就用const。
11、整型只使用C++中 的int,不要用short/long等,用<stdint.h>中的int16_t等代替。不要使用 uint32_t 等无符号整型,除非你是在表示一个位组(bit pattern)而不是一个数值。
12、64位友好
1)printf的格式要特殊处理,参考原文
2) sizeof(void *) != sizeof(int)。用intptr_t获得指针大小的整数。
3) gcc用__attribute__((packed))设置结构体对齐方式。
4)64位常量用LL或ULL为后缀,如0x1234LL,3ULL。
5)可以用宏 #ifdef _LP64 判断64位系统。
13、谨慎用宏,尽量用内联函数、枚举和常量代替。
14、Use 0 for integers, 0.0 for reals, NULL for pointers, and '\0' for chars.
15、尽量用 sizeof(varname) 代替 sizeof(type) 。
五、命名约定
1、通用命名规则:函数命名、变量命名、文件命名应具有描述性,不要要过度缩写,类型和变量应该是名词,函数名可以用“命令性”动词。
2、文件名:全部小写,可以包含_或-。如my_usefull_class.cpp。
3、类型名:大写字母开头的驼峰式,不含下划线,如MyClass。所有类型名(类/结构体/类型定义(typedef)/枚举)都适用。
4、变量名:一律小写,单词间以下划线相连(my_exciting_local_variable)。类的成员发量以下划线结尾(my_exciting_member_variable_),全局变量g_开头,常量k开头驼峰式(kDaysInAWeek)。
5、函数名:普通函数大写开头的驼峰式(AddTableEntry()),存取函数与变量名匹配(int num(), void set_num()),短小的可以内联的函数可以使用小写字母。
6、命名空间:全小写,下划线分隔,基于项目名称和目录结构。
7、枚举值名:全大写,下划线分隔(MY_EXCITING_ENUM_VALUE)。
8、宏命名:最好不用,用的话同枚举值命名。
六、注释
这是一门艺术
七、格式
1、每行不超过80字符
2、尽量不用非ASCII字符,必须用时用utf-8格式
3、2个空格作为缩进(这个4个比较好?)
4、函数声明的排版也是艺术
5、其他排版问题也是艺术,尽量提高可读性
八、最最重要的
团队合作,保持一致。没有最好的个人,只有最好的团队。