6 命名约定
最重要的一致性规则是命名管理. 命名的风格能让我们在不需要去查找类型声明的条件下快速地了解某个名字代表的含义: 类型, 变量, 函数, 常量, 宏, 等等, 甚至. 我们大脑中的模式匹配引擎非常依赖这些命名规则.
命名规则具有一定随意性, 但相比按个人喜好命名, 一致性更重要, 所以无论你认为它们是否重要, 规则总归是规则.
6.1. 通用命名规则
总述
函数命名, 变量命名, 文件命名要有描述性; 少用缩写.
说明
尽可能使用描述性的命名, 别心疼空间, 毕竟相比之下让代码易于新读者理解更重要. 不要用只有项目开发者能理解的缩写, 也不要通过砍掉几个字母来缩写单词.
int price_count_reader; // 无缩写
int num_errors; // "num" 是一个常见的写法
int num_dns_connections; // 人人都知道 "DNS" 是什么
int n; // 毫无意义.
int nerr; // 含糊不清的缩写.
int n_comp_conns; // 含糊不清的缩写.
int wgc_connections; // 只有贵团队知道是什么意思.
int pc_reader; // "pc" 有太多可能的解释了.
int cstmr_id; // 删减了若干字母.
注意, 一些特定的广为人知的缩写是允许的, 例如用 i 表示迭代变量和用 T 表示模板参数.
模板参数的命名应当遵循对应的分类: 类型模板参数应当遵循 类型命名 的规则, 而非类型模板应当遵循 变量命名 的规则.
6.2 文件命名
总述
文件名要全部小写, 可以包含下划线 (_
) 或连字符 (-
), 依照项目的约定. 如果没有约定, 那么 “_
” 更好.
说明
可接受的文件命名示例:
- my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
- myusefulclass_test.cc // _unittest 和 _regtest 已弃用.
C++ 文件要以 .cc 结尾, 头文件以 .h 结尾. 专门插入文本的文件则以 .inc 结尾, 参见 头文件自足.
不要使用已经存在于 /usr/include 下的文件名 ( 注: 即编译器搜索系统头文件的路径), 如 db.h.
通常应尽量让文件名更加明确. http_server_logs.h 就比 logs.h 要好. 定义类时文件名一般成对出现, 如 foo_bar.h 和 foo_bar.cc, 对应于类 FooBar.
内联函数必须放在 .h 文件中. 如果内联函数比较短, 就直接放在 .h 中.
6.3 类型命名
规则:类型名的每个单词首字母均应大写,不要包含下划线。
例如:MyExcitingClass,MyExcitingEnum。
规则:所有类型命名(包括:类、结构体、类型别名、枚举、类型模板参数)均使用相同约定,即以大写字母开始,每个单词首字母均大写,不包含下划线。
例如:
//类和结构体
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
//类型定义
typedef hash_map<UrlTableProperties *, string>
PropertiesMap;
// using 别名
using PropertiesMap = hash_map<UrlTableProperties *,
string>;
// 枚举
enum UrlTableErrors { ...
6.4 变量命名
规则:变量 (包括函数参数) 和数据成员名一律小写,单词之间用下划线连接。类的成员变量以下划线结尾,但结构体的就不用。
6.4.1 普通变量命名
string table_name; // 好 - 用下划线
string tablename; // 好 - 全小写
string tableName; // 差 - 混合大小写
6.4.2 类数据成员
规则:不管是静态的还是非静态的,类数据成员都可以和普通变量一样,但要以下划线结尾。
class TableInfo {
...
private:
string table_name_; // 好 - 后加下划线
string tablename_; // 好
static Pool<TableInfo>* pool_; // 好
};
6.4.3 结构体变量
规则:不管是静态的还是非静态的,结构体数据成员都可以和普通变量一样,不用像类那样以下划线结尾。
struct UrlTableProperties {
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
6.5 常量命名
规则:声明为 constexpr 或 const 的变量,或在程序运行期间其值始终保持不变的量,命名时以 k 开头,大小写混合。例如:
const int kDaysInAWeek = 7;
规则:所有静态存储类型的变量 (例如静态变量或全局变量) 都应当以此方式命名。对于其他存储类型的变量,如自动变量等,这条规则是可选的。如果不采用这条规则,就按照一般的变量命名规则命名。
6.6 函数命名
规则:常规函数使用大小写混合,accessors 和 mutators 函数则要与变量名匹配。
规则:一般来说,函数名的每个单词首字母大写 (即 “驼峰命名法” 或 “帕斯卡命名法”),没有下划线。对于首字母缩写而成的单词,更倾向于将它们视作一个单词进行首字母大写 (例如,写作 StartRpc()而非 StartRPC())。
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
6.7 命名空间命名
规则:命名空间以小写字母命名。最高级命名空间的名字应取决于项目名称。注意避免嵌套命名空间和常见的顶级命名空间的名字发生冲突。
规则:命名空间名字尽量不要用缩写。命名空间中的代码极少需要涉及命名空间的名称,因此没有必要在命名空间中使用缩写。
6.8 枚举命名
规则:枚举命名应和常量或宏的命名一致,如:kEnumName 或是 ENUM_NAME。
规则:单独的枚举值应该采用常量的命名方式,宏方式的命名也可以接受。枚举名UrlTableErrors (以及 AlternateUrlTableErrors) 是类型,所以要用大小写混合的方式。
enum UrlTableErrors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
OK = 0,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2,
}
6.9 宏命名
规则:尽量不要使用宏,如果要用,应这样命名: MY_MACRO_THAT_SCARES_SMALL_CHILDREN。
#define ROUND(x) ...
#define PI_ROUNDED 3.0
6.10 命名规则的特例
总述
如果你命名的实体与已有 C/C++ 实体相似, 可参考现有命名策略.
bigopen(): 函数名, 参照 open() 的形式
uint: typedef
bigpos: struct 或 class, 参照 pos 的形式
sparse_hash_map: STL 型实体; 参照 STL 命名约定
LONGLONG_MAX: 常量, 如同 INT_MAX