C++编程规范 (参考Google C++ Style Guide)
核心原则:代码应该是为了阅读而编写的,而不仅仅是为了机器执行。保持代码风格的一致性比个人偏好更重要。
1. 头文件规则
通常一个.cpp文件对应一个.h文件,当然也有特例,main函数入口cpp文件没有对应的.h文件,只有纯虚函数的接口类只有.h文件,没有.cpp文件
1.1 #define防止多重包含
所有头文件都应该使用#define 防止头文件被多重包含,这个多重包含指的是一个cpp编译过程中不被多次包含,如果有多个cpp都调用,那这个文件还是会被包含多次,所有头文件中不要做定义。
实例,在x_msg_task.h头文件中:
#ifndef X_MSG_TASK_H_
#define X_MSG_TASK_H_
#endif
| 注意:标准 C++ 保留了以双下划线开头或包含双下划线的标识符。请避免使用
__X_MSG_TASK_H__,推荐使用单下划线后缀。
1.2 减少头文件依赖
尽量减少 .h 文件中 #include 的数量。如果头文件包含了其他文件,这些文件的任何改变都将导致包含你头文件的所有代码重新编译。
- 指针或引用:如果在头文件中仅使用某类的指针或引用,应优先使用前置声明(如
class XThread;),并在.cpp文件中引入该类的头文件。 - 实体对象:如果类中包含实体对象成员,则必须引入对应的头文件。
1.3 头文件中不导入命名空间
严禁在头文件中使用 using 导入整个命名空间(例如 using namespace std;),以防止污染调用者的命名空间并引发冲突。
- 在头文件中应使用完整的命名空间前缀(如
std::string)。 - 命名空间的导入操作应限定在
.cpp文件中。
2. 格式规则
2.1 空格还是制表位
只使用空格进行缩进,严禁使用 Tab 键。每次缩进 4 个空格。(避免不同环境下tab按键缩进不一样)
注意:google规范是缩进2个空格
2.2 括号格式
左右括号都单独起一行
if(true)
{
//
}
注意:google规范是左大括号和if判断语句同行,根据个人习惯选择
//google规范
if(true) {
//
}
3. 命名约定
函数、变量、文件的命名应具有高度描述性,拒绝过度缩写。类型和变量名应为名词,函数名应包含“命令性”动词。
| 实体类型 | 命名规范 | 示例 | 说明 |
|---|---|---|---|
| 文件名 | 全小写,下划线连接 | my_file.cpp |
|
| 类型名 | 大驼峰式 (PascalCase) | MyFunctionClass |
包含类、结构体、类型定义 (typedef/using)、枚举 |
| 普通函数 | 大驼峰式 (PascalCase) | AddTableEntry() |
不包含下划线 |
| 变量名 | 全小写,下划线连接 | local_variable |
|
| 类成员变量 | 全小写,下划线结尾 | num_entries_ |
用于与普通局部变量做区分 |
| 宏定义 | 全大写,下划线连接 | PI_ROUNDED |
|
| 枚举值 | 全大写,下划线连接 | ERROR_OUT_OF_MEMORY |
枚举类型名称本身使用大驼峰式 |
成员存取函数示例:
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. 类规则
4.1 构造函数的职责
构造函数中只应进行没有实际业务逻辑的简单初始化。复杂的业务逻辑初始化应尽量集中在专门的 Init() 方法中执行。
4.2 结构体和类
仅当对象只有数据(即纯数据集合,没有复杂业务方法)时使用 struct,其他情况一概使用 class。两者成员变量建议采用不同的命名规则以示区分。
4.3 继承与多重继承
-
优先使用组合,只有在逻辑上确有必要时才使用继承。
-
如果必须使用继承,只允许使用
public继承。 -
严格限制多重继承:如果必须使用多重继承,只能有一个基类包含实现,其余基类必须是纯接口类,以避免内部空间分配和菱形继承问题。
4.4 接口
接口是指满足特定条件的类,建议以大写字母 I 开头(非强制约束)。
- 接口类内部只能包含纯虚函数(
= 0)和静态函数。
4.6 声明次序
在类中使用声明次序如下:public、protected、private
每一块中,声明次序一般如下:
- 构造函数
- 析构函数
- 成员函数(包含静态成员函数)
- 数据成员(包含静态数据成员)
5. Doxygen注释规则
5.1 文件注释
文件注释通常放在整个文件开头。
-
项目注释
/** * @mainpage 项目注释 * @author 作者 * @version 版本 * @date 2019 年 07 月 10 日 */ -
文件注释
/** * @file 文件名 * @brief 简介 * @details 细节 */
5.2 类定义注释
格式如下:
/**
* @brief 类的简单概述
* @details 类的详细概述,说明其核心职责和注意事项
*/
class MyClass { ... };
5.3 常量/变量注释
int max_connections_; /**< 最大允许的并发连接数 */
5.4 函数注释
/**
* @brief 函数功能简介
* @param[in] param_name 参数含义说明
* @param[out] result_name 输出参数说明
* @return 返回值的含义及状态码说明
*/
int DoSomething(int param_name, int* result_name);
5.5 Doxygen使用
- Macbook上安装方法
# 安装 Doxygen
brew install doxygen
# 验证版本
doxygen --version
# 安装 Graphviz (用于生成类图和依赖图)
brew install graphviz
具体用法:
- 生成配置文件: 在终端中进入你的项目目录,运行
doxygen -g。这会生成一个名为Doxyfile的纯文本文件。 - 编辑配置: 用你平时的代码编辑器(如
VS Code、Sublime甚至系统自带的文本编辑)打开这个Doxyfile。 - 修改关键项: 这个文件虽然长,但大多数是默认设置。你只需要搜索并修改这几个最常用的关键项(把等号右边的值改成你需要的):
PROJECT_NAME = "你的项目名称"INPUT = ./src(把路径改成你存放.h和.cpp源代码的目录)RECURSIVE = YES(开启子目录递归扫描)EXTRACT_ALL = YES(提取所有代码元素的注释,即使没有按照 Doxygen 规范写)HAVE_DOT = YES(如果你用 Brew 安装了 graphviz,开启这个可以生成精美的类图)
- 生成文档: 保存文件后,在终端运行
doxygen Doxyfile(或直接运行doxygen),文档瞬间生成。最终文档在html文件夹中的index.html文件
6. Clang-Format检查格式
文档写得再好,靠人工 Code Review 去数“这里是不是缩进了4个空格”、“大括号有没有换行”也是极其低效的。
“本规范的排版格式统一由 .clang-format 配置文件约束。提交代码前,必须使用 Clang-Format 工具进行自动格式化。” 这能彻底终结团队里关于代码排版的口水战。
6.1 安装clang-format
在Macbook上安装
brew install clang-format
# 验证是否安装成功:
clang-format --version
6.2 生成配置文件
Clang-Format 的核心就在于项目根目录下的 .clang-format文件。你可以基于 Google 的默认风格生成一个基础模板,然后根据你刚刚制定的规范进行微调。
- 生成基础模板: 在你的项目根目录(或者你的代码存放目录)下,运行以下命令:
clang-format -style=google -dump-config > .clang-format
这会在当前目录下生成一个包含所有配置项的 .clang-format文件。
2. 按照你的规范修改关键配置: 用文本编辑器打开 .clang-format 文件。为了完美匹配你前面总结的规范(4个空格缩进、左右大括号单独换行),你需要找到并修改以下几个核心字段:
# 基于 Google 风格作为底层基础
BasedOnStyle: Google
# 1. 缩进设置 (对应你的 2.1 规范:4个空格)
IndentWidth: 4
TabWidth: 4
UseTab: Never # 严禁使用 Tab
# 2. 大括号换行风格 (对应你的 2.2 规范:左右大括号单独起一行)
# Allman 风格就是标准的左右大括号都换行的风格
BreakBeforeBraces: Allman
# 3. 行宽限制
ColumnLimit: 80 # 或者根据你们团队屏幕大小改成 100/120
# 4. 指针和引用的对齐方式 (靠近类型还是靠近变量)
PointerAlignment: Left # 例如:int* a; (Google 标准)
# 5. 禁止将短函数放在单行
# 可选值:None, InlineOnly, Empty, Inline, All
AllowShortFunctionsOnASingleLine: None
# 6. 禁止将短代码块放在单行 (比如简单的 if 语句)
# 可选值:Never, Empty, Always
AllowShortBlocksOnASingleLine: Never
# 7. 禁止将简单的 if/while 语句单行显示
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
6.3 安装生成注释插件
Clang-Format 是一个“格式化工具”, 它的工作范围仅限于调整现有代码的空格、缩进、换行和对齐。如果按照格式要求添加注释,需要使用VSCode上的Doxygen Documentation Generator插件
- 在
VS Code扩展市场搜索并安装插件:Doxygen Documentation Generator。 - 安装后,在
.cpp或.h文件的顶部,或者在函数/类定义的上一行,输入/**然后按下回车键。 - 插件会自动读取你的函数名、参数(
@param)和返回值(@return),并瞬间生成一个完美的Doxygen注释模板,你只需要在里面填空即可。
设置 VS Code 的 settings.json
-
在
VS Code中按下快捷键Cmd + Shift + P(Mac)打开命令面板。 -
输入
Open Settings (JSON),选择 “首选项:打开用户设置 (JSON)”。
将以下配置复制粘贴到你的 settings.json 的最外层大括号 {} 内:
{
// ==========================================
// Doxygen 插件自定义配置 (最终纯净版)
// ==========================================
// 1. 触发字符:输入 /** 后回车触发
"doxdocgen.c.triggerSequence": "/**",
// 2. 注释块风格:采用 Javadoc 风格 (/** ... */)
"doxdocgen.generic.style": "javadoc",
// 3. 开启智能方向识别,自动添加 [in] / [out]
"doxdocgen.generic.includeDirectionOfParams": true,
// 4. 作者与日期格式
"doxdocgen.generic.authorName": "你的名字/花名",
"doxdocgen.generic.authorEmail": "your_email@example.com",
"doxdocgen.generic.dateFormat": "YYYY 年 MM 月 DD 日",
// 5. 元素排列顺序 (简介 -> 空行 -> 参数 -> 返回值)
"doxdocgen.generic.order": [
"brief",
"empty",
"param",
"return"
],
// 6. 文件头注释模板
"doxdocgen.file.fileTemplate": [
"@file {name}",
"@brief ",
"@details "
],
// 7. 类/结构体注释模板
"doxdocgen.class.classTemplate": [
"@brief ",
"@details "
]
}
命令行中使用clang-format
# 预览格式化结果,不修改原文件
clang-format main.cpp
# 直接格式化并保存
clang-format -i main.cpp
# 批量化格式化
find src -name "*.cpp" -o -name "*.h" | xargs clang-format -i
终极解放:集成到VSCode中
1.安装插件: C/C++ 插件(通常已经安装)
2.开启保存时格式化:打开VSCode设置(cmd+,),搜索 Format On Save ,并勾选Editor:Format On Save
3.指定默认格式化工具:搜索 Default Formatter ,将其设置为 C/C++
以后按下保存之后,会读取 .clang-format 文件,把代码整理规范