C++代码格式规范引导(一):引言与代码布局

来源:互联网 发布:对淘宝店铺怎么投诉 编辑:程序博客网 时间:2024/05/21 06:18

“房子是用来住的,不是用来炒的”,这是当前最耳熟的一句房政。在我们编码界,有一句话具有着同样的经典意义,也同样耳熟能详,“代码是用来看的,不仅是用来跑的”。至此,不论是新鸟还是老手都能码出比较整齐的可读的代码。然而,有很多代码具有多种公认的风格,不同的人或不同的时间,代码都可能在公认风格之间切换,再加上一些突发奇想、特立独行的设计,项目代码中也能算是百家争鸣。其弊端大致有两个:降低了代码阅读的效率;误解代码含义,导致功能BUG。
此处针对项目开发过程中的常用编码,制定一个初步方案。仍需根据不同的团队、项目各自调整。
参考《Google开源项目风格指南:C++风格指南》

代码布局

从整体来看,常见代码可以分成如下几块:头文件引用(#include)、命名空间(namespace)、定义(typedef)、宏(Macros)、常量(const)、枚举(enum)、结构体(struct)、类(class)、全局变量(Global Variable)、全局方法(Global Function)、声明(extern)。其中宏、全局变量在C++中不被推荐使用,声明也往往用的较少。设计代码布局如下:

#includenamespace {constenumstruct*Global Variable*Global Functionclass}
  1. 头文件引用(#include)是代码格式中唯一一个置于命名空间外的代码块。其主要考虑到每一个头文件中,代码块都有各自的命名空间,无需置于当前命名空间中;同时置于当前命名空间中时,当前命名空间中对象的定义/声明对于头文件中的代码可视为全局,可能导致命名空间污染。
  2. 除头文件引用外的其他代码块均需要置于有效的命名空间(namespace)内,即不应该出现匿名空间的对象。命名空间的存在是为了分隔代码,处于匿名空间中的对象均为C++的基本类型(int、char等等)。
  3. const与enum定义的常量往往针对简单类型(int, std::string等),对于该代码文件其他内容无依赖,所以第一优先级定义。
  4. struct应用于定义单纯的数据结构(带有行为应定义为class),可以是STL标准库,也可以是自定义的类型(class/struct)。因不具备行为,所以置于function和class之前定义。
  5. 全局方法(Global Function)与全局变量(Global Variable)做整体看,可当做特殊的类,匿名的单件对象,所以定义在标准类之前。但,全局变量禁用,全局函数推荐少用,避免全局污染、并发冲突等等问题。可使用类中的静态变量、静态方法替代,但若类名仅做命名空间效果,无实际意义,则勿要强制将全局函数封装成类。
  6. 定义(typedef)比较特殊,通俗来说,是对复杂结构的命名,体现对象赋予的业务含义。在布局中未体现,是因为typedef无法过于专断。可以出现在struct之前,亦可出现在struct之后,包括交替出现;当class作为数据容器时,排版与struct一致。
  7. 宏(Macros)不推荐使用,若无法避免,建议收入单独的文件中定义。
  8. 声明(extern),可分为两种场景:1,为了减少头文件引用而进行声明,不推荐使用。2,在单文件内,因定义类型的顺序,需要声明后定义的类型,可使用(注:需防止定义相互嵌套)。总体来讲,声明少用。

代码布局规范细则

  1. 代码块排序如上所示
  2. 文件起始必须为有效的代码或注释
  3. 文件结束必须有且仅有一个空行
  4. 相邻代码块之间保持一个空行
  5. 所有代码块从第一列开始,无需在代码块前保留空格
  6. 除头文件引用置于命名空间外,其他代码块不允许匿名空间
  7. 一个文件中,只能定义一个命名空间
  8. 每一行代码必须以非空格字符结尾,不允许保留多余的空格
  9. 每一行代码除最前面以连续空格进行排版外,不允许出现连续空格
  10. 代码中不应出现TAB,所有TAB必须以4个空格代替
  11. 所有宏(包括函数内使用的宏等)使用从第一列开始,无需随代码缩进
  12. 命名规范:驼峰命名法

代码布局规范示例(cpp)

#include <std::string>namespace CodeStype {const std::string CODE_STYLE_DESCRIPTION = "CodeStyleDescription";enum CodeStyleType{    CST_CamelCase,    CST_UpperCamelCase};typedef std::vector<std::string> StringVector;struct CodeDataHolder{    std::string name;    int32_t id;};typedef std::vector<CodeDataHolder> CodeDataCollector;std::string toString(int32_t inData){    return "";}class CodeStyleProject{public:private:};}

代码布局规范示例(hpp)

#ifndef __FILE_NAME_HPP_171019__#define __FILE_NAME_HPP_171019__#include <std::string>namespace CodeStype {/// Code Block}#endif

hpp文件相对cpp文件,多了防止头文件重复包含的宏定义。其细则如下:

  1. #ifndef/#define/#include之间无需添加空行
  2. #endif需要与上一层代码块之间保持1空行
  3. 宏名称定义规范:
    • 双下划线开头;双下划线结尾
    • 关键字使用文件名,全大写,单词之间以单下划线隔开
    • 文件名后添加HPP
    • HPP后添加6位时间,防止重名文件