这篇文章整理了一份适合项目协作的 C/C++ 代码规范,内容以现有团队规范为基础,并参考 Google C++ Style Guide。文末补充了统一的 Git 提交规范,方便在日常开发里直接套用。

参考资料:Google C++ Style Guide

一、命名规范

1. 变量

局部变量

1
int i_am_a = 0;
2
static std::string i_am_b = "";

全局变量

1
int g_i_am_a = 0;
2
std::string g_i_am_b = "";

类成员变量

1
int _i_am_a;
2
static std::string _i_am_b;

结构体成员变量

1
int i_am_a;
2
static std::string i_am_b;

2. 常量

1
const int kIamConst = 1;
2
const int kUbuntu_20_04 = 1;

说明:

  • 常量使用 k 前缀。
  • 多单词采用大驼峰。
  • 带版本或数字的命名可以直接保留数字段。

3. 枚举

1
enum IamEnum
2
{
3
kIamEnumA = 0,
4
kIamEnumB,
5
};
6
7
enum class IamEnum
8
{
9
kIamEnumA = 0,
10
kIamEnumB,
11
};
12
13
enum class IamEnum : int
14
{
15
kIamEnumA = 0,
2 collapsed lines
16
kIamEnumB,
17
};

4. 宏

1
#define I_AM_MACRO_A 10
2
#define I_AM_MACRO_B "i am b"
3
#define I_AM_MACRO_C(x) ...

说明:

  • 宏名全部大写。
  • 单词之间使用下划线分隔。
  • 能用 constconstexpr、内联函数替代时,优先不要用宏。

5. 结构体

1
struct IamStruct
2
{
3
int i_am_a;
4
std::string i_am_b;
5
};

6. 类

1
class IamClass
2
{
3
public:
4
IamClass(void);
5
~IamClass(void);
6
7
int IamFuncA(int arg_a);
8
9
protected:
10
std::string _i_am_a;
11
12
private:
13
int _i_am_b;
14
static std::string _i_am_c;
15
};

7. 函数

1
int IamFuncA(int i_am_a, const string& i_am_b);

说明:

  • 函数名使用大驼峰。
  • 参数名使用小写加下划线。
  • 引用或指针参数要能从命名和类型上体现输入输出语义。

8. 函数指针与回调

1
typedef void (*FP_{FUNCTION_NAME})(int i_am_a, const string& i_am_b);
2
FP_{FUNCTION_NAME} fp_ptr; // Local variable
3
FP_{FUNCTION_NAME} _fp_ptr; // Member variable
4
FP_{FUNCTION_NAME} g_fp_ptr; // Global variable
5
6
typedef std::function<void(int i_am_a, const string& i_am_b)> FN_{FUNCTION_NAME};
7
FN_{FUNCTION_NAME} fn_ptr; // Local variable
8
FN_{FUNCTION_NAME} _fn_ptr; // Member variable
9
FN_{FUNCTION_NAME} g_fn_ptr; // Global variable

9. 命名空间

1
namespace mynamespace
2
{
3
...
4
namespace mysubnamespace
5
{
6
7
} // namespace mynamespace::mysubnamespace
8
...
9
} // namespace mynamespace

10. 头文件保护

1
#ifndef __[SYSTEM_NAME_ACRONYM]_[MOUDLE_NAME]_[HEADER_NAME]_H__
2
#define __[SYSTEM_NAME_ACRONYM]_[MOUDLE_NAME]_[HEADER_NAME]_H__
3
...
4
#endif // __[SYSTEM_NAME_ACRONYM]_[MOUDLE_NAME]_[HEADER_NAME]_H__

二、注释规范

1. 文件头注释

1
/** @file module_api.h
2
* @brief Module API.
3
* A module must implement the following APIs and be compiled as a shared library.
4
* @author Ermazi Wang
5
* @version 1.0
6
* @date 2012-01-01
7
* @copyright Heli Co., Ltd. All rights reserved.
8
*/

2. 接口注释

外部调用接口,或者逻辑复杂的接口,尽量补充接口注释。

1
/** @fn bool Init(const char* arg1, int& arg2)
2
* @brief This function is the first one to be called before other APIs.
3
* Module initialization should be completed in this function.
4
* @param [in] arg1 Argument 1.
5
* @param [in,out] arg2 Argument 2.
6
* @return Result of module initialization.
7
*/
8
9
/** @fn void Uninit()
10
* @brief This function will be called to perform module uninitialization
11
* before exiting the module. It is a good chance to clean all data
12
* structures here.
13
* @return None
14
*/

三、代码目录结构

1
ExampleProject/
2
|-- src
3
|-- conf
4
|-- bin
5
|-- lib
6
|-- build
7
|-- doc
8
|-- CMakeLists.txt
9
`-- README.md

建议:

  • src 放源码。
  • conf 放配置。
  • lib 放第三方库或内部库。
  • doc 放文档。
  • 构建产物与源码分离,避免目录混乱。

四、编码建议

  • 代码文件尽量不超过 1000 行。
  • 函数尽量不超过 100 行。
  • 函数参数个数尽量不超过 5 个。
  • 圈复杂度尽量不超过 5。
  • 统一使用 4 个空格缩进。
  • 尽可能处理所有编译告警。
  • 宁用组合,慎用继承。
  • 不要堆叠过深的继承链。
  • 不要写技巧性过强的代码。
  • 能简单就不要复杂。
  • 如非必要,不要增加新的抽象实体。
  • 不要过度设计。
  • 在可读性和扩展性之间做平衡。
  • 可读性是代码质量的重要指标。
  • 好的命名是可读性的核心组成部分。
  • 及时重构,消除异味代码。

五、Git 提交规范

提交信息统一采用下面的格式:

1
类型: 描述

1. 类型定义

类型含义
feat新功能
fix修复问题
refactor代码重构
docs文档修改
chore其他修改

2. 提交示例

1
feat: 新增底盘控制
2
fix: 修复校验错误
3
refactor: 优化协议解析
4
docs: 更新说明文档
5
chore: 调整构建脚本

3. 使用建议

  • 一次提交尽量只做一类事情。
  • 描述直接写结果,不写无意义词汇,例如“修改了一下”。
  • 优先使用能体现业务变化或技术动作的短语。
  • 文档、脚本、配置类调整不要混进功能提交。

六、落地建议

如果项目准备长期维护,这份规范至少要在三个位置保持一致:

  • 仓库根目录的开发文档。
  • 新成员入项说明。
  • Code Review 和 Git 提交检查流程。

规范本身不是目的,降低协作成本、减少理解偏差、提升可维护性才是目的。只要团队已经约定,就要稳定执行,而不是每个模块各写一套风格。