本文档规定 synthrt 仓库通用的代码组织与 C++ 编写原则。具体格式以仓库根目录的 .clang-format 为准。
公开头文件放在 synthrt/include/synthrt/模块 下,源文件放在 synthrt/lib/模块 下。公开头文件与源文件应按模块保持对应关系。例如,synthrt/include/synthrt/Core/PackageHandle.h 对应 synthrt/lib/Core/PackageHandle.cpp。
仅供实现使用的私有头文件放在对应的 synthrt/lib/模块 目录中,并使用 _p.h 后缀。私有头文件会增加实现之间的耦合,应尽量少用。
仅供多个实现文件复用且不独立编译的实现片段可以使用 .cpp.inc 后缀。普通声明仍应放在头文件中,普通实现仍应放在 .cpp 文件中。
文件名采用大驼峰命名并与其中的主要类型一致,例如 PackageHandle.h 与 PackageHandle.cpp。程序入口 main.cpp 保持小写。
- 类名及其他类型名使用大驼峰命名。
- 函数名、参数名、变量名和命名空间使用小驼峰命名。表示二元操作左右两侧的
LHS与RHS是仅有的全大写变量名例外。 - 枚举成员使用大驼峰命名。
- 类的私有数据成员使用
m_前缀。PImpl 中相互关联的实现指针与声明对象指针是例外,使用与 stdcorelib 一致的_impl与_decl。公有数据成员不使用前缀。 - getter 使用所读取的属性名,例如
value()。 - setter 使用
set加属性名,例如setValue()。 - 全局非静态变量使用
g_前缀,全局静态变量使用s_前缀。应尽量避免引入全局可变状态。 - 命名空间结束处不添加注释。
所有改动过的 C++ 文件在提交前使用仓库的 .clang-format 格式化。不要手工制造与格式化配置相冲突的对齐或换行。
初始化表达式的类型为指针时,使用 auto name = ...,不要写 auto *name = ...。auto 会自动推导出指针类型,额外的 * 不提供信息。
短小且需要暴露定义的函数可以在类内实现,或在头文件的类定义之后使用 inline 实现。不要仅仅为了减少一个 .cpp 文件而把较长实现放进公开头文件。
公开声明使用 LLVM 风格的 /// 文档注释,不使用 \brief。使用 Doxygen 的 \c 标识符、\a 参数、\note、\warning 等命令表达结构化含义。
注释应解释约束、所有权、生命周期以及当前实现必须如此设计的原因。不要用注释记录代码以前的样子或修改历史,这些信息由版本控制保存。
注释使用美式英语。不要用破折号连接从句,也不要用分号代替应有的断句。
析构函数不要使用 override 关键字。 头文件内继承的类不要使用 final。
引用块从上到下依次为系统库、标准库、第三方库、项目内被依赖的其他目标和当前目标内的头文件。不同来源的引用块之间留一个空行,同一引用块中的头文件应来自同一个库。不要依赖其他头文件偶然提供的传递引用。
在头文件中引用项目公开头文件时使用完整公共路径:
#include <synthrt/Core/PackageHandle.h>如果被引用的头文件与当前头文件位于同一目录,并且具有预引入或自动生成等特殊用途,也可以使用双引号直接引用。
在源文件中,同一构建目标内的头文件一律使用双引号直接引用。与源文件同名的公开头文件和 _p.h 私有头文件具有最高优先级,必须组成源文件最上方的第一个引用块。系统库、标准库、第三方库和项目内其他目标的头文件依次放在其后。当前目标内的其余头文件具有最低优先级,必须组成最底部的独立引用块。
#include "PackageHandle.h"
#include "PackageHandle_p.h"
#include <sys/types.h>
#include <filesystem>
#include <memory>
#include <stdcorelib/str.h>
#include "SynthUnit.h"
#include "ContribLocator.h"