文章目录
Glory C++ 编码规范
概述
见名知意:
- 命名可以无限长。为了准确描述对象,无需简化用词(易造成歧义)
- 如有缩写(acronym),必须补充完整含义
无歧义
- 当前代码段无歧义
- 当前命名空间无歧义
- 当前项目无歧义:需要对整个项目有较好的理解。
- 当前系统无歧义:如尽量避免全局使用 ProcessInfo(Windows系统自带命名等) 等系统API对象
- 广义上无歧义:需要更大的知识空间,可暂时略去
注释
- 注释是为了对命名的局限性进行补充;原则上,无法做到见名知意的任何对象,均应补充注释;
- 注释应说明为什么而不是什么;
- 注释规范,使用 doxygen 类似形式,示例如下:
- 注释内容不要紧跟注释符 ‘//’ ,空一格
/* @file 文档名,可以默认为空,DoxyGen会自己加 @date 文档修改的日期:3/16/2006 @author 作者名 @version 版本标识 @copyright 版权,GNU Public License. @remark 备注,或remarks @brief 简易说明,产生的文档不会缩进无关键词 @details 详细说明,产生的文档不会缩进无关键词 @pre 函数前置条件,比如对输入参数的要求 @param 参数及其意义 @return 返回值 @see 引用 @override 重写 @throws 异常类及抛出条件 @warning 函数使用中需要注意的地方 @note 提醒 @bug bug @code 代码示例 CDC* dc = AfxGetMainWindow()->GetDC(); Bitmap bmp(dc , "test.bmp"); AfxGetMainWindow()->ReleaseDC(dc); @endcode 代码示例结束 */ // 文件注释可以详细; // 类原则上必须注释; // 函数按需注释; // 变量注释如此处形式
细节及示例
注意:代码提交之前必须格式化,格式化规则见最后章节。
文件名
小写字母下划线分隔,如:
user_model.h、user_model.cc测试工程文件加后缀 ’
xx_test.cc’- 所有测试源码均放置于工程根目录的
/test子目录下 - 测试用例(函数)使用
xx_case()形式,也可单独剥离为文件 xx_case.cc
- 所有测试源码均放置于工程根目录的
文件防重复包含均使用
#pragma once而不是老旧标准文件
#include路径应参考常规C++编码规范,如《C++ Primer》,概述为:#include "dir/foo.h" // foo.cc 优先包含自身头文件 #include <cmath> // c #include <fstream> // c++ #include <eigen_util.h> // base repository #include "user_model.h" // current project
类名、类型定义、命名空间等
- 大驼峰
- 不要在头文件的全局作用域引入某个命名空间
- 如无必要,不使用多重继承
- 如无必要,不使用运算符重载
- 如无必要,不使用友元
// namespace 例外(参考STL) namespace ipec { // 命名空间内的内容无需缩进。如不匹配,格式化规则(最后章节)会自动对齐该规则。下同,均略 template <typename T> class Point { } } // namespace ipec template <typename T> struct PointHash { std::size_t operator()(const ipec::Point<T>& point) const { std::size_t h1 = std::hash<T>{}(point.x()); std::size_t h2 = std::hash<T>{}(point.y()); return h1 ^ (h2 << 1); // Combine the hashes } }; using IntPoint = ipec::Point<int>; using DoublePoint = ipec::Point<double>;成员变量(重要!)
必须以下划线结尾,以便与局部变量区分。
namespace Chemical // 建议改为小写 { class Compound { public: explicit Compound(std::vector<Element> const &elements); explicit Compound( std::string const &chemical_formula, std::string const &name = "", double excitation_energy = 0); bool Invalid() const { return elements_.empty(); } std::string String() const; public: // simple class simple use, no need to getElements std::vector<Element> elements_; std::string name_; std::string formula_; double excitation_energy_; }; } // namespace Chemical函数
- 大驼峰——整体雷同 Google编码风格。
- 如无必要,不使用异常
// interface 以 I 开头 class UserController { public: enum UrlTableErrors { // 嵌套类型的定义放在前面而不是后面 kOK = 0, kErrorOutOfMemory, kErrorMalformedInput, }; public: // 不要吝啬 public:类型与成员函数要分开 bool HasPermission() const; // Google 的大驼峰形式(客户✅); 个人更偏向: has_permission protected: bool doSth(); // 非 public 成员函数以小写字母开头(客户✅); 本人更偏向: do_sth_ 或 _do_sth private: Channel* channel_; // 头文件中只使用了指针或引用则使用向前声明,而非头文件 }其他
整体符合 Google编码风格。请自行使用 C++ 创始人 BS 的《 The C++ Programming Language 》汲取细节,此处仅挑出易被忽视的重点部分或模糊部分:
- 缩进:4 个空格(方便列编辑以及更好的web端展示)
- 如无必要,不使用宏定义;如使用,应全部大写
- 枚举类型使用最新的 c++ 规范而不是 C 规范:
enum class - Windows、Qt、CUDA 均有自身的编码规范。可取交集,以子领域优先为原则
// 复杂类型必须使用 using 声明,而不是 typedef template <typename T> using twin = pair<T,T>; // 常量、枚举值均以 k 开头 const int kDaysInAWeek = 7; // 局部(临时)变量也使用下划线风格 int num_users; // 重载时必须 override virtual void DoSth() override; // 单参构造函数必须使用 explicit 修饰 explicit UserController(int xx); // #if 等宏定义最好顶行书写 #if __cplusplus >= 202002L // supports C++20 #else // non-support C++20 #endif // 尽量加括号,不要让读者产生额外负担(虽然不必要)。 // 如: num_users >> 1+2; // 应尽量写为: num_users >> (1+2);- 优先级
概览:
优先级(高→低) 运算符 说明 结合性 1 ::作用域解析(scope resolution) 自左向右 2 ()[].->函数调用、下标、成员访问、指针成员 自左向右 3 ++--(后缀)后自增、后自减 自左向右 4 ++--(前缀)前自增、前自减 自右向左 !~逻辑非、按位取反 自右向左 +-(一元)正号、负号(单目) 自右向左 *&取值(解引用)、取地址 自右向左 ()(强制类型转换)C 风格/函数风格强制转换 自右向左 sizeof取大小 自右向左 newnew[]deletedelete[]动态内存分配与释放 自右向左 5 */%乘、除、取余 自左向右 6 +-加、减 自左向右 7 <<>>位移运算 自左向右 8 <><=>=关系运算符(大小比较) 自左向右 9 ==!=相等、不等 自左向右 10 &按位与 自左向右 11 ^按位异或 自左向右 12 ` ` 按位或 13 &&逻辑与 自左向右 14 ` ` 15 ?:条件运算符(三目) 自右向左 16 =+=-=*=/=%=<<=>>=&=^=`=` 赋值及复合赋值运算符 17 throw抛出异常 自右向左 18 ,逗号运算符 自左向右
格式化
- 代码提交前必须使用
clang-format格式化 - 已置于各项目根目录,如缺失可自行添加
- 可根据需要定制、修改
BasedOnStyle: Google
# UseTab: Always
TabWidth: 4
IndentWidth: 4
ColumnLimit: 80
Cpp11BracedListStyle: false
SeparateDefinitionBlocks: Always
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignTrailingComments: true
AlignArrayOfStructures: Left
AccessModifierOffset: -4
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
BreakConstructorInitializers: AfterColon
PackConstructorInitializers: NextLine
BinPackArguments: false
BinPackParameters: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: false
IndentExternBlock: false
IndentWrappedFunctionNames: false
MaxEmptyLinesToKeep: 1
SortIncludes: false
# InsertNewlineAtEOF: true
InsertTrailingCommas: Wrapped
EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true
CompactNamespaces: false
BreakStringLiterals: true
AllowAllArgumentsOnNextLine: false
AlwaysBreakAfterReturnType: None
AllowAllParametersOfDeclarationOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BeforeLambdaBody: true


