• 命名
    • 通用命名
      • 规则2.1.1 标识符命名使用驼峰风格
    • 文件命名
      • 建议2.2.1 C++文件以.cpp结尾,头文件以.h结尾
      • 建议2.2.2 C++文件名和类名保持一致
    • 函数命名
    • 类型命名
      • 建议2.4.1 避免滥用 typedef或者#define 对基本类型起别名
    • 变量命名
      • 规则2.5.1 类的成员变量命名使用小驼峰。
    • 宏、常量、枚举命名

    命名

    通用命名

    常见命名风格有:驼峰风格(CamelCase)大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开。按连接后的首字母是否大写,又分: 大驼峰(UperCamelCase)和小驼峰(lowerCamelCase)

    内核风格(unix_like)单词全小写,用下划线分割。如:'test_result'

    匈牙利风格在‘大驼峰’的基础上,加上前缀;前缀用于表达类型或用途。如:'uiSavedCount', 'bTested'

    规则2.1.1 标识符命名使用驼峰风格

    不考虑匈牙利命名,在内核风格与驼峰风格之间,根据存量代码的情况,我们选择驼峰风格。

    类型命名风格
    类类型,结构体类型,枚举类型,联合体类型等类型定义大驼峰
    函数(包括全局函数,作用域函数,成员函数)大驼峰(接口部分可加前缀,如XXX_函数名)
    全局变量(包括全局和命名空间域下的变量,类静态变量),局部变量,函数参数,类、结构体和联合体中的成员变量小驼峰
    常量(const),枚举值k+大小写混合
    大写+下划线
    命名空间全小写

    注意:上表中常量是指全局作用域、namespace域、类的静态成员域下,以 const或constexpr 修饰的基本数据类型、枚举、字符串类型的变量。上表中变量是指除常量定义以外的其他变量,均使用小驼峰风格。

    文件命名

    建议2.2.1 C++文件以.cpp结尾,头文件以.h结尾

    我们推荐使用.h作为头文件的后缀,这样头文件可以直接兼容C和C++。我们推荐使用.cpp作为实现文件的后缀,这样可以直接区分C++代码,而不是C代码。

    目前业界还有一些其他的后缀的表示方法:

    • 头文件: .hh, .hpp, .hxx
    • cpp文件:.cc, .cxx, .C对于本文档,我们默认使用.h和.cpp作为后缀。

    建议2.2.2 C++文件名和类名保持一致

    C++的头文件和cpp文件名和类名保持一致,使用下划线小写风格。

    如下:

    • database_connection.h
    • database_connection.cpp结构体,命名空间,枚举等定义的文件名类似。

    函数命名

    函数命名统一使用大驼峰风格,一般采用动词或者动宾结构。接口部分可加前缀,如XXX_函数名。

    1. class List {
    2. public:
    3. void AddElement(const Element& element);
    4. Element GetElement(const unsigned int index) const;
    5. bool IsEmpty() const;
    6. bool MCC_GetClass();
    7. };
    8. namespace utils {
    9. void DeleteUser();
    10. }

    类型命名

    类型命名采用大驼峰命名风格。所有类型命名——类、结构体、联合体、类型定义(typedef)、枚举——使用相同约定,例如:

    1. // classes, structs and unions
    2. class UrlTable { ...
    3. class UrlTableTester { ...
    4. struct UrlTableProperties { ...
    5. union Packet { ...
    6. // typedefs
    7. typedef std::map<std::string, UrlTableProperties*> PropertiesMap;
    8. // enums
    9. enum UrlTableErrors { ...

    对于命名空间的命名,建议全小写:

    1. // namespace
    2. namespace osutils {
    3. namespace fileutils {
    4. }
    5. }

    建议2.4.1 避免滥用 typedef或者#define 对基本类型起别名

    除有明确的必要性,否则不要用 typedef/#define 对基本数据类型进行重定义。优先使用<cstdint>头文件中的基本类型:

    有符号类型无符号类型描述
    int8_tuint8_t宽度恰为8的有/无符号整数类型
    int16_tuint16_t宽度恰为16的有/无符号整数类型
    int32_tuint32_t宽度恰为32的有/无符号整数类型
    int64_tuint64_t宽度恰为64的有/无符号整数类型
    intptr_tuintptr_t足以保存指针的有/无符号整数类型

    如果模块有自己的定义,请使用统一的typedef来定义类型:

    1. typedef signed char VOS_INT8;
    2. typedef unsigned char VOS_UINT8;
    3. #if __WORDSIZE == 64
    4. typedef unsigned long int VOS_UINTPTR;
    5. #else
    6. typedef unsigned int VOS_UINTPTR;
    7. #endif

    如果模块为了封装某个类型的信息,方便后续的扩展,可以使用typedef来重新定义。

    1. typedef uint8_t DeviceID;
    2. // ...
    3. // 若干版本后扩展成 16-bit
    4. typedef uint16_t DeviceID;

    有特殊作用的类型typedef void Handle;注意:*不要使用 #define 进行别名定义,并且在C++11以后推荐使用using来定义类型。

    除上述理由外,应避免给其本数值类型别名定义。因为类型别名可读性并不好,隐藏了基本数值类型信息,如位宽,是否带符号。滥用举例:

    1. typedef uint16_t MyCounter;
    2. // ...
    3. int Foo(...) {
    4. MyCounter c;
    5. // ...
    6. while (c >= 0) {
    7. printf("counter = %d\n", c);
    8. // ...
    9. }
    10. // ...
    11. }

    对'MyCounter'是否可能小于0,打印时用'%d'还是'%u'都不是很直观,极容易引入上述类似缺陷。

    变量命名

    通用变量命名采用小驼峰,包括全局变量,函数形参,局部变量,成员变量。

    1. std::string tableName; // Good: 推荐此风格
    2. std::string tablename; // Bad: 禁止此风格
    3. std::string path; // Good: 只有一个单词时,小驼峰为全小写

    规则2.5.1 类的成员变量命名使用小驼峰。

    1. class Foo {
    2. private:
    3. std::string fileName; // 不添加任何作用域前缀或者后缀
    4. };

    当构造函数参数和成员变量重名时,可通过this->来引用成员变量。

    1. class MyClass {
    2. public:
    3. MyClass(int myVar) : myVar(myVar) { // OK,初始化列表允许同名入参初始化同名成员
    4. if (NeedNewVar()) {
    5. this->myVar = GetValue(); // 注意不要漏掉this->,否则就成了给入参赋值
    6. }
    7. }
    8. private:
    9. int myVar;
    10. };

    宏、常量、枚举命名

    宏采用全大写,下划线连接的格式。常量、枚举值使用k+大小写混合。函数局部 const 常量和类的普通const成员变量,使用小驼峰命名风格。

    1. #define MAX(a, b) (((a) < (b)) ? (b) : (a)) // 仅对宏命名举例,并不推荐用宏实现此类功能
    2. enum TintColor { // 注意,枚举类型名用大驼峰,其下面的取值是k+大小写混合
    3. kRed,
    4. kDarkRed,
    5. kGreen,
    6. kLightGreen
    7. };
    8. int Func(...) {
    9. const unsigned int bufferSize = 100; // 函数局部常量
    10. char *p = new char[bufferSize];
    11. ...
    12. }
    13. namespace utils {
    14. const unsigned int kFileSize = 200; // 全局常量
    15. }