C++代码格式规范引导(1):引言与代码布局
Contents
“房子是用来住的,不是用来炒的”,这是当前最耳熟的一句房政。在我们编码界,有一句话具有着同样的经典意义,也同样耳熟能详,“代码是用来看的,不仅是用来跑的”。至此,不论是新鸟还是老手都能码出比较整齐的可读的代码。然而,有很多代码具有多种公认的风格,不同的人或不同的时间,代码都可能在公认风格之间切换,再加上一些突发奇想、特立独行的设计,项目代码中也能算是百家争鸣。其弊端大致有两个:降低了代码阅读的效率;误解代码含义,导致功能BUG。 此处针对项目开发过程中的常用编码,制定一个初步方案。仍需根据不同的团队、项目各自调整。 参考《Google开源项目风格指南:C++风格指南》
代码布局
从整体来看,常见代码可以分成如下几块:头文件引用(#include)、命名空间(namespace)、定义(typedef)、宏(Macros)、常量(const)、枚举(enum)、结构体(struct)、类(class)、全局变量(Global Variable)、全局方法(Global Function)、声明(extern)。其中宏、全局变量在C++中不被推荐使用,声明也往往用的较少。设计代码布局如下:
|
|
- 头文件引用(#include)是代码格式中唯一一个置于命名空间外的代码块。其主要考虑到每一个头文件中,代码块都有各自的命名空间,无需置于当前命名空间中;同时置于当前命名空间中时,当前命名空间中对象的定义/声明对于头文件中的代码可视为全局,可能导致命名空间污染。
- 除头文件引用外的其他代码块均需要置于有效的命名空间(namespace)内,即不应该出现匿名空间的对象。命名空间的存在是为了分隔代码,处于匿名空间中的对象均为C++的基本类型(int、char等等)。
- const与enum定义的常量往往针对简单类型(int, std::string等),对于该代码文件其他内容无依赖,所以第一优先级定义。
- struct应用于定义单纯的数据结构(带有行为应定义为class),可以是STL标准库,也可以是自定义的类型(class/struct)。因不具备行为,所以置于function和class之前定义。
- 全局方法(Global Function)与全局变量(Global Variable)做整体看,可当做特殊的类,匿名的单件对象,所以定义在标准类之前。但,全局变量禁用,全局函数推荐少用,避免全局污染、并发冲突等等问题。可使用类中的静态变量、静态方法替代,但若类名仅做命名空间效果,无实际意义,则勿要强制将全局函数封装成类。
- 定义(typedef)比较特殊,通俗来说,是对复杂结构的命名,体现对象赋予的业务含义。在布局中未体现,是因为typedef无法过于专断。可以出现在struct之前,亦可出现在struct之后,包括交替出现;当class作为数据容器时,排版与struct一致。
- 宏(Macros)不推荐使用,若无法避免,建议收入单独的文件中定义。
- 声明(extern),可分为两种场景:1,为了减少头文件引用而进行声明,不推荐使用。2,在单文件内,因定义类型的顺序,需要声明后定义的类型,可使用(注:需防止定义相互嵌套)。总体来讲,声明少用。
代码布局规范细则
- 代码块排序如上所示
- 文件起始必须为有效的代码或注释
- 文件结束必须有且仅有一个空行
- 相邻代码块之间保持一个空行
- 所有代码块从第一列开始,无需在代码块前保留空格
- 除头文件引用置于命名空间外,其他代码块不允许匿名空间
- 一个文件中,只能定义一个命名空间
- 每一行代码必须以非空格字符结尾,不允许保留多余的空格
- 每一行代码除最前面以连续空格进行排版外,不允许出现连续空格
- 代码中不应出现TAB,所有TAB必须以4个空格代替
- 所有宏(包括函数内使用的宏等)使用从第一列开始,无需随代码缩进
- 命名规范:驼峰命名法
代码布局规范示例(cpp)
|
|
代码布局规范示例(hpp)
|
|
hpp文件相对cpp文件,多了防止头文件重复包含的宏定义。其细则如下:
- #ifndef/#define/#include之间无需添加空行
- #endif需要与上一层代码块之间保持1空行
- 宏名称定义规范:
- 双下划线开头;双下划线结尾
- 关键字使用文件名,全大写,单词之间以单下划线隔开
- 文件名后添加_HPP_
- _HPP_后添加6位时间,防止重名文件
Author 朦呆农码
LastMod 2017-10-20