C++ 代码规范
本规范旨在提升团队协作效率与代码质量,通过统一编码风格,确保代码的可读性、可维护性与可扩展性。规范的制定有助于减少沟通成本、规避潜在错误,并为代码的长期演进奠定坚实基础,保障项目高效交付与稳定运行。
命名规范(匈牙利前缀 + 小驼峰命名法)
统一总规则:所有变量、函数统一使用小驼峰命名法,变量统一添加类型前缀。
1. 函数参数及普通变量命名
参数命名严格遵循「类型前缀 + 语义化名称」,命名需简洁明确、语义清晰、贴合用途,禁止无意义缩写,固定类型前缀如下:
double:前缀d(示例:dOffset、dRadius)vector:前缀vec(示例:vecStudent、vecPersons)bool:前缀b(示例:bIsValid、bEnable)point:前缀pt(示例:ptStart、ptEnd)int:前缀n(示例:nCount、nIndex)float:前缀f(示例:fScale、fAngle)char:前缀c(示例:cFlag、cSeparator)string:前缀str(示例:strName、strPath)- 枚举类型(enum):前缀
e(示例:eMode、eStatus) - 指针类型:前缀
p(示例:pPerson、pBuffer)
2. 全局变量命名
支持两种规范,二选一即可:
- 在变量命名规则基础上,添加
g_前缀。示例:g_dGlobalScale、g_vecGlobalPersons; - 全大写字母,单词之间用下划线分隔。示例:
GLOBAL_SCALE、GLOBAL_FEATURES。
3. 常量命名
支持两种规范,二选一即可:
- 在变量命名规则基础上,添加
c_前缀。示例:c_dMaxOffset、c_nMinCount; - 全大写字母,单词之间用下划线分隔。示例:
MAX_OFFSET、MIN_COUNT。
4. 函数命名
统一使用小驼峰命名法,首字母小写,后续每个单词首字母大写,遵循「动词 + 名词」结构,语义明确无歧义,示例:processStudent、calculateOffset、checkValidity。
类与结构体专属规范
本小节整合所有类、结构体、成员权限、成员变量相关全部规则,统一管理、便于查阅执行。
1. 类/结构体命名
采用大驼峰命名法,首字母大写,名称直接体现核心用途,简洁无歧义,示例:Circle、StudentInfo、Point2D。
2. 类成员权限管控
- 成员变量必须为私有权限(private),如需外部访问、修改,必须提供对应的get/set方法,严禁外部直接修改私有成员变量;
- 不同权限的函数和成员,必须单独划分独立代码块,禁止不同权限内容混合穿插(private、protected、public代码块严格分开书写,不可交叉);
- 所有私有成员变量,必须集中放在类声明的最后位置,单独一个private代码块统一声明,与成员函数完全分离。
- 子类实现父类虚函数时,需要同时添加virtual和override关键字,确保虚函数继承关系清晰,避免隐式覆盖导致的逻辑异常。
- 类的公有方法(public权限)必须编写注释,注释需清晰说明方法功能、参数含义、返回值类型及使用注意事项,提升代码可维护性和可读性。
正确示例
// 父类声明
class Base
{
public:
// 公有虚函数,必须添加注释说明功能
/**
* @brief 处理人数据,核心业务入口
* @param dParam 处理参数,范围:0.0~100.0
* @return bool 处理成功返回true,失败返回false
*/
virtual bool processData(double dParam) = 0;
};
// 子类实现,同时添加virtual和override关键字
class Student : public Base
{
public:
// 公有方法必须添加注释,与父类虚函数注释呼应
/**
* @brief 重写父类方法,处理学生人数据
* @param dParam 学生处理偏移参数,范围:0.0~100.0
* @return bool 处理成功返回true,参数非法返回false
*/
virtual bool processData(double dParam) override
{
// 业务逻辑实现
return true;
}
private:
void initData();
private:
double m_dOffset;
vector<person*> m_vecStudent;
bool m_bIsValid;
};
class Base2
{
public:
// public权限的get/set方法,单独一个代码块,专供外部访问/修改成员变量
double getOffset() const;
void setOffset(double dOffset);
private:
// private权限内部工具函数,单独一个代码块,与其他权限完全区分
void initData();
private:
// 成员变量统一为private权限,单独代码块,置于类声明最后
double m_dOffset;
vector<person*> m_vecStudent;
bool m_bIsValid;
};
错误示例
// 父类声明
class Base
{
public:
// 错误:公有虚函数未添加注释
virtual bool processData(double dParam) = 0;
};
// 子类实现,存在两处错误
class Student : public Base
{
public:
// 错误1:公有方法未添加注释;错误2:未同时添加virtual和override关键字
bool processData(double dParam) // 仅写override或仅写virtual,均不符合规范
{
// 业务逻辑实现
return true;
}
private:
// 错误:私有方法和成员变量穿插混合,位于同一个private块内
void initData();
double m_dOffset;
vector<person*> m_vecStudent;
};
class Base2
{
public:
double getOffset() const;
void setOffset(double dOffset);
// 错误:成员变量设为public,允许外部直接修改
bool m_bIsValid;
private:
// 错误:私有方法和成员变量穿插混合,位于同一个private块内
void initData();
double m_dOffset;
vector<person*> m_vecStudent;
};
3. 类成员变量命名
在普通变量「类型前缀+语义化名称」的基础上,额外添加固定前缀m_,严格区分普通变量与类成员变量,示例:m_dOffset、m_vecStudent、m_bIsValid、m_ptCenter。
通用格式规范
1. 声明与定义分离
- 函数声明与定义必须强制分离,函数声明置于对应的.h头文件中,函数实现定义置于同名.cpp文件中;
- 头文件首行必须添加头文件守卫【
#pragma once】; - 头文件中严禁使用【
using namespace】,彻底避免命名空间污染。
示例
// 头文件 XXX.h(仅存放函数声明)
#pragma once // 强制头文件守卫
void initData();
// 同名源文件 XXX.cpp(仅存放函数实现定义)
#include "XXX.h"
void initData()
{
// 业务逻辑实现
}
2. 花括号书写
- 函数定义、
for、while、if、else、switch、class、struct等所有语句,左右花括号必须单独占一行,与对应语句对齐; if、for、while等条件/循环语句,即便内部只有1行逻辑,也必须加花括号包裹,严禁省略花括号;- 花括号规则不适用于变量初始化列表,初始化列表可正常同行书写;
- 严禁左花括号紧跟语句末尾、同行书写。
正确示例
// 花括号单独成行,符合规范
vector<person*> processStudent()
{
if (bIsValid)
{
return {}; // 单行逻辑,强制加花括号
}
// 初始化列表不受花括号规则约束
vector<int> vecNums = {1, 2, 3, 4};
return {};
}
错误示例
// 错误:左花括号与语句同行
vector<person*> processStudent() {
if (bIsValid) {
return {};
}
// 错误:单行逻辑省略花括号
for (int i = 0; i < 5; i++)
cout << i << endl;
// 错误:单行逻辑省略花括号
while (bIsRunning)
updateStatus();
}
3. 空行使用
- 函数内不同逻辑块之间,添加适量空行区分模块(类似写作文区分自然段),提升代码可读性;
- 函数与函数之间保留1个空行,类内成员函数的声明之间、定义之间保留1个空行;
- 禁止连续多个空行,严禁代码首尾多余空行。
4. 指针使用
- 所有指针在使用前必须执行判空操作,杜绝空指针访问导致程序崩溃;
指针判空推荐极简写法:if (pPerson):判断指针非空,可理解为「如果指针存在」if (!pPerson):判断指针为空,可理解为「如果指针不存在」
推荐写法
// 推荐极简判空写法
Person* pPerson = XXX();
if (pPerson) // 先判非空,再安全使用
{
pPerson->XXX();
}
if (!pPerson) // 判空后按需输出日志
{
// LOG(WARNING) << "pPerson is null";
}
不推荐/错误写法
// 不推荐:冗余冗余判空写法,不符合规范
Person* pPerson = XXX();
if (pPerson != nullptr) // 冗余多余
{
pPerson->XXX();
}
if (pPerson == NULL) // 写法不统一、冗余
{
// ...
}
// 严重错误:未判空直接使用指针
pPerson->XXX();
判空同时需要输出日志、跳过当前逻辑的,可使用项目统一封装的断言宏,简化代码:
for (person* pPerson : vecPersons)
{
LOG_WARN_CONTINUE_UNLESS(pPerson,"pPerson is null");
}
// 上述代码等价于完整判空+日志+跳过逻辑,代码更简洁
for (person* pPerson : vecPersons)
{
if (!pPerson)
{
LOG(WARNING) << "pPerson is null";
continue;
}
}
- 严禁指针链式调用,必须逐级拆解、逐级判空,避免链式空指针崩溃。
推荐逐级判空写法
void func(person_factory* pFactory)
{
if (!pFactory)
{
return;
}
archer* pArcher = pFactory->Archer();
if (!pArcher)
{
return;
}
Teacher* pTeacher = pArcher->m_pteacher;
}
禁止的链式调用写法
void func(person_factory* pFactory)
{
// 严重错误:链式调用,任意一级为空都会直接崩溃
Teacher* pTeacher = pFactory->Archer()->m_pteacher;
}
5. 缩进
嵌套代码逐层缩进,层级对齐清晰,禁止乱缩进、内层代码不缩进,保证代码结构一目了然。
6. 空格
- 算术运算符(+、-、、/、%)、比较运算符(==、!=、<、>、<=、>=)、赋值运算符(=、+=、-=、=、/=)两侧,各保留1个空格;
- 函数参数列表逗号后加1个空格,逗号前无空格;
if/for/while关键字与括号之间加1个空格,括号内部首尾无空格;- 函数名与括号之间严禁加空格。
7. 注释
- 单行注释统一使用
//,注释内容与//之间保留1个空格,仅用于标注关键逻辑、特殊处理、易错坑点; - 严禁无效注释、冗余注释、注释与代码逻辑不符。
8. 代码质量与工程通用
变量定义规则
变量在使用时就近定义,严禁统一集中在函数/代码块开头定义,符合 Effective C++ 规范,避免无效资源占用。
嵌套层级控制
严格控制代码嵌套层级,优先使用反判断提前返回/跳过,扁平化代码逻辑,大幅提升可读性与可维护性,禁止超过3层的深层嵌套。
函数长度限制
单个函数代码行数严格控制在200行以内,复杂、重复的逻辑必须提取为独立公共函数,严禁超大函数、单函数承载多段无关业务。
逻辑复用
公共业务逻辑、通用工具逻辑必须封装为独立函数,严禁复制粘贴代码后仅修改局部内容,保证同一段逻辑只需要修改一处即可全量生效。
其他强制规则
- 严禁使用无意义魔法数字,固定数值统一定义为常量,常量命名优先使用全大写、单词下划线分隔格式;
- 超长代码行在运算符前换行,换行后与上一行对齐缩进;
switch语句每个case独立缩进,每个case逻辑必须加花括号包裹,break紧跟逻辑结尾,多case共用逻辑必须添加注释说明。
9. 匿名空间使用规则
仅在当前文件使用的局部函数,统一放入当前cpp文件的匿名命名空间,严禁在全局作用域直接书写,避免全局命名冲突、重定义错误,提升代码封装性。
10. 全局配置信息
多文件复用的固定属性名、常量配置,统一在独立头文件中集中定义,使用constexpr 修饰,禁止在多个文件中复制硬编码字符串、数值,便于统一维护、一键修改。
11. auto关键字使用
简单基础类型禁止使用auto关键字,auto仅可在以下场景使用,保证代码类型可读性、无歧义:
- 定义lambda表达式时(必须使用auto);
- 类型名称过长、书写繁琐时,如STL容器迭代器、复杂模板类型。
12. 数学计算(后端)
- 凡是分母为变量的,必须考虑分母为0的情况。
- 浮点数之间的比较应使用 MathUtils 下的方法
13. 线程创建(后端)
- 创建线程应使用线程池 ThreadPool 统一管理
代码提交信息规范
禁止空提交信息,所有提交必须标注清晰、可追溯。
1. bug修复提交
严格按照以下格式填写,保证bug可追溯、根因与方案对应:
[bug 编号] bug标题
根本原因:XXX(精准说明bug核心成因,禁止模糊描述,如“代码错误”“逻辑异常”)
解决方法:XXX(详细说明修复方案、修改模块、核心逻辑,与根因完全对应)
自行发现、无bug编号的问题,编号项可省略。
2. 功能相关提交
功能开发、优化、调整等提交,按照以下格式填写,明确修改内容:
[功能名] 核心修改内容(简洁明确)
补充说明:修改细节、修改原因、新增/优化的核心逻辑(可选)
3. 其他通用修改
非bug、非特定功能的通用修改,直接清晰填写修改内容即可。

浙公网安备 33010602011771号