文章目录
1 头文件
1.1 #define的保护
有头文件都应该使用#define防止头文件被多重包含( multiple inclusion) ,命名格式应当是:<PROJECT>_<PATH>_<FILE>_H_
。为保证唯一性,头文件的命名应基于其所在项目源代码树的全路径。例如,项目foo中的头文件foo/src/bar/baz.h按如下方式保护:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_
1.2 内联函数
只有当函数只有10行甚至更少时才会将其定义为内联函数
1.3 函数参数顺序
定义函数时,参数顺序为:输入参数在前,输出参数在后
1.4 包含文件的名称和次序
次序如下: C库、 C++库、 其他库的.h、 项目内的.h
2 构造函数
2.1 构造函数的职责
构造函数中只进行那些没有实际意义的( 简单初始化对于程序执行没有实际的逻辑意义, 因为成员变量的“有意义”的值大多不在构造函数中确定)初始化, 可能的话,使用Init()方法集中初始化为有意义的数据。
2.2 明确的构造函数
对于单参数构造函数使用C++关键字explicit
2.3 结构体和类
仅当只有数据时使用struct,其它一概使用class
2.4 继承
- 所有的继承必须是public
- 数据成员应该始终为private
- 含有虚函数的父类中,定义虚析构函数绝对必要
- 当重定义派生的虚函数时, 在派生类中明确声明其为virtual
2.5 接口
接口类即为抽象类,声明了纯虚函数,不能被直接实例化,其析构函数必须声明为虚函数。一般以Interface为后缀命名。
2.6 操作符重载
除少数特定情况下,不要重载操作符
2.7 存取控制
- 将数据私有化,并提供相关的存取函数
- 存取函数的定义一般内联的头文件中
2.8 声明次序
先public再protected最后private
每一块中的声明次序如下:
- typedefs和enums;
- 常量;
- 构造函数;
- 析构函数;
- 成员函数,含静态成员函数;
- 数据成员,含静态数据成员
3 其他C++特性
3.1 引用参数
按引用传递的参数必须加上const
3.2 缺省参数
禁止使用缺省函数参数
3.3 类型转换
命名用static_cast<>()等C++的类型转换, 不要使用 int y = (int)x或 int y = int(x)
- static_cast: 和C风格转换相似可做值的强制转换, 或指针的父类到子类的明确的向上
转换; - const_cast:移除const属性
3.4 前置自增和自减
迭代器和模板类型来说,要使用前置自增(自减),效率更高
3.5 const的使用
强烈建议在任何可以使用的情况下都要使用const
- 如果函数不会修改传入的引用或指针类型的参数,这样的参数应该为const
- 尽可能将函数声明为const,访问函数应该总是const,其他函数如果不会修改任何数据成员也应该是const,不要调用非const函数,不要返回对数据成员的非const指针或引用
3.6 整型
- C++内建整型中, 唯一用到的是int, 如果程序中需要不同大小的变量, 可以使用<stdint.h>中的精确宽度( precise-width) 的整型,如int16_t
- 使用断言声明变量为非负数,不要使用无符号型
3.7 预处理宏
使用宏时要谨慎,尽量以内联函数、枚举和常量代替之
3.8 0和NULL
整数用0,实数用0.0,指针用NULL,字符(串)用’\0’
3.9 sizeof
尽可能用sizeof(varname)代替sizeof(type)
4 命名约定
4.1 文件名命名
文件名要全部小写,可以包含下划线( _)或短线( -),按项目约定来
my_useful_class.cpp
my-useful-class.cpp
myusefulclass.cpp
对于包含大量内联代码的类,可以有三个文件
url_table.h //The class declaration
url_table.cpp // The class definition.
url_table-inl.h // Inline functions that include lots of code
4.2 类型命名
- 类型命名每个单词以大写字母开头,不包含下划线: MyExcitingClass、 MyExcitingEnum。
- 所有类型命名——类、结构体、类型定义( typedef)、枚举——使用相同约定,例如:
// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// typedefs
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
// enums
enum UrlTableErrors { ...
4.3 变量命名
变量名一律小写,单词间以下划线相连,类的成员变量以下划线结尾,如my_exciting_local_variable、 my_exciting_member_variable_。
string table_name; // OK - uses underscore.
string tablename; // OK - all lowercase.
string tableName; // Bad - mixed cas
4.4 常量命名
在名称前加k: kDaysInAWeek
4.5 函数命名
- 普通函数:
函数名以大写字母开头,每个单词首字母大写,没有下划线:
AddTableEntry()
DeleteUrl() - 存取函数:
存取函数要与存取的变量名匹配,这儿摘录一个拥有实例变量num_entries_的类:
class MyClass {
public:
...
int num_entries() const { return num_entries_; }
void set_num_entries(int num_entries) { num_entries_ = num_entries; }
private:
int num_entries_;
};
- 其他短小的内联函数名也可以使用小写字母
4.6 命名空间
命名空间的名称是全小写的,其命名基于项目名称和目录结构: google_awesome_project
4.7 枚举命名
- 枚举值应全部大写,单词间以下划线相连: MY_EXCITING_ENUM_VALUE。
- 枚举名称属于类型,因此大小写混合: UrlTableErrors。
enum UrlTableErrors {
OK = 0,
ERROR_OUT_OF_MEMORY,
ERROR_MALFORMED_INPUT,
}