C++ 编码规范(给自己定的)

原文:http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/contents/

源自Google 编码规范,按照自己的情况,给自己定一个标准

1.头文件

1.1.#define 保护

所有头文件都应该使用#define 防止头文件被多重包好,命名格式是:_<PROJECT>_<FILE>_H_


1.2.头文件依赖

能用前置声明的地方尽量不使用#include

原因:减少编译依赖


1.3.内联函数

只有当函数只有10行以下时彩将其定义为内联函数

特殊:析构函数包含隐式的代码,往往比看到的长,循环或switch函数不应该内联,递归函数和虚函数的内联命令往往会被忽略


1.5.函数参数顺序

顺序依次为: 输入参数,输入/输出参数,输出参数


2.作用域


2.1.命名空间

命名空间基于项目名,不要使用using


2.1.1匿名名字空间

在.cpp文件中,鼓励使用匿名名字空间替代static,不要在.h中使用匿名名字空间


2.2.嵌套类

当一个类只会被另一个类访问时,使用嵌套类,不要将嵌套类定义成公有


2.3.非成员函数、静态成员函数和全局函数

使用静态成员函数或名字空间内的非成员函数,尽量不要用裸的全局函数,如果只是在.cpp文件中调用,使用匿名命名空间


2.4.局部变量

将函数变量尽可能置于最小作用域内,并在变量声明时进行初始化,如果循环中的变量是一个对象,每次进出作用域都要进行构造,析构,那么移动到循环外


2.5.静态和全局变量

禁止使用class类型的静态或全局变量,只能是原生数据类型以及对应的数据/结构体/指针,不要使用函数返回值初始化静态变量(不理解),不要在多线程代码中使用非const的静态变量


3.类

3.1.构造函数的职责

构造函数只进行那么没什么意义的初始化,比如指针赋值null等,可能的话,使用Init()方法集中初始化有意义的数据(构造函数不能使用异常,构造函数失败会使对象进入不确定态,构造函数不应该调用虚函数)


3.2默认构造函数

如果一个类定义了若干成员变量(不包括父类中的变量)又没有其他构造函数,必须定义一个默认构造函数,把内部状态初始化成一致/有效的值,否则编译器将生成一个糟糕的默认构造函数,对对象进行不确定的初始化


3.3.显示构造函数

对单个参数的构造函数使用C++关键字explicit,防止对象隐式转换


3.4.拷贝构造函数

仅在代码中需要拷贝一个类对象的时候使用拷贝构造函数,大部分情况下都不需要,可以使用宏 DISALLOW_COPY_AND_ASSIGN


3.5.结构体VS.类

仅当只有数据时使用struct,其他都是用class,仿函数(functors)和特性(traits) 可以使用struct


3.6.继承

所有继承必须是public的,如果想使用私有继承,那么应该实现为成员对象

继承适用在is-a 组合适用在has-a

如果类中有虚函数,析构函数也应该是虚函数,数据成员在任何情况下都必须是私有的

重载一个虚函数,必须明确声明为virtual,使得阅读者判断是否是虚函数不用检查所有父类


3.7.多重继承

所有父类除第一个外都是纯接口类,才允许使用多重继承,这些类以I开头


3.8.接口

接口:

只有纯虚函数和静态函数(析构函数例外) 

没有非静态数据成员

没有定义任何构造函数,如果有,也不能带有参数,并且必须为protected

如果他是一个子类,也只能从满足上述条件并以I为前缀的类继承


3.9.运算符重载

尽量不要使用运算符重载,除非使用一些STL算法


3.10.存取控制

将所有数据成员声明为private,并根据需要提供对应的存取函数,一般在头文件中定义为内联函数


3.11.声明顺序

类的访问控制字段声明顺序依次为:public protected private

每个区段内的声明通常按以下顺序:

typedefs 和枚举

常量

构造函数

析构函数

成员函数,含静态成员函数

数据成员,含静态数据成员


宏DISALLOW_COPY_AND_ASSIGN 的调用放在private区段的末尾


3.12.编写简单函数

如果函数超过40行,考虑在不影响程序结构的前提下对其进行分割,如果需要使用其中的一小段代码,考虑分割为更加简短并易于管理的若干函数


5.1.引用参数

输入参数是值参或const引用,输出参数为指针


5.2.函数重载

仅在输入参数类型不同,功能相同时使用重载函数(含构造函数),不要用重载函数模拟缺省参数,不要包含缺省参数(自己觉得)


5.3.缺省参数

不要使用缺省参数


5.4.变长数组和alloca()

不要使用变长数组和alloca()


5.5.友元

通常友元应该定义在同一文件内


5.6.异常

谷歌不推荐使用异常,我也不会用


5.7.运行时类型识别

不要使用RTTI


5.8.类型转换

使用static_cast替代C风格的值转换

用const_cast去掉const限定符

用reinterpret_cast 指针类型和整形,或其他指针间进行不安全的互相转化

dynamic_cast 除测试代码外,不要使用


5.9.流

使用printf和 scanf代替流


5.10.前置自增和自减

不考虑返回值的话,使用前置自增


5.11.const的使用

在任何可能的情况下都要使用const


5.12.整形

尽量不要使用unsigned类型,使用断言保护数据


5.14.预处理宏

尽量不要使用宏


5.15. 0和NULL

整数用0,实数用0.0 指针用NULL 字符(串)用'\0'


5.16. sizeof

尽量使用sizeof(varname) 代替sizeof(type),因为变量可能会在未来的编码中改变类型


6.1.通用命名规则

函数名,变量命名,文件命名,应具备描述性,不要过度缩写,类型和变量应该是名词,函数名可以用命令性动词,除非缩写在其他地方都非常普遍,否则不要使用


6.2.文件命名

文件名称的每个单词首字母均大写,不包含下划线


6.3.类型命名

变量命名一律使用小驼峰命名法,类型名称的每个单词首字母均大写,不包含下划线(类,结构体,类型定义,枚举)


6.4.变量命名

变量命名一律使用小驼峰命名法,类的成员变量加前缀m,如:

tableName

mTableName


6.5.常量命名

所有编译时常量,无论是局部的,全局的,还是类中的,都和其他变量稍微区别一下,k后接大写字母开头的单词,如:

const int kDaysInAWeek = 7;


6.6.函数命名

函数命名一律使用大驼峰命名法


6.8.枚举命名

枚举的命名和常量命名一致


6.9.宏命名

如:MY_MACRO_THAT_SCARES_SMALL_CHILDREN


7.3.类注释

每个类的定义都要附加一份注释,描述类的功能和用法


7.4.函数注释

函数声明处注释描述函数功能,定义处描述函数实现

函数声明:

注释位于声明之前,对函数功能及用法进行描述

注释内容:

函数的输入输出

对类成员函数而言:函数调用期间对象是否需要保持引用参数,是否会释放这些参数

如果函数分配了空间,需要由调用者释放

参数是否可以为NULL

是否存在函数使用上的性能隐患

如果函数是可重入的,其同步前提是什么?(多任务)

函数定义:

每个函数定义时要用注释说明函数功能和实现要点,不要从.h文件或其他地方复制注释


7.5.变量注释

如果变量可以接受NULL 或-1等警戒值,需加以说明


7.6.实现注释

对于代码中巧妙的,晦涩的,有趣的,重要的地方加以注释。

行注释:在比较隐晦的地方要在行尾加入注释,在行尾空两格进行注释

如果需要连续进行多行注释,可以使之对齐获得更好的可读性

向函数传入NULL,bool 或整数时,要注释说明含义


7.7.标点,拼写,和语法

注释的通常写法是包含正确大小写和结尾句号的完整语句


7.8.TODO注释

对那些临时的,短期的解决方案,或以为够好,但仍不完美的代码使用TODO注释

注释使用全大写的字符串TODO在随后的圆括号里写入身份标识


8.1.行长度

每一行代码字符数不超过80

特例

如果一行注释包含了超过80字符的命名或URL,出狱复制粘贴的方便允许该行超过80字符

包含长路径的#include 可以超出80行,但应该尽量避免

头文件保护可以无视该原则


8.2.非ASCII字符

谷歌推荐使用UTF-8编码,可是项目一般使用多字节


8.4.函数声明与定义

函数返回类型和函数名在同一行,参数也尽量放在同一行,如果同一行文本太多:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1,
                                             Type par_name2,
                                             Type par_name3) 
{
    DoSomething();
    ...
}


如果函数声明成const 关键字const 应与最后一个参数位于同一行


8.5.函数调用

尽量放在同一行,将实参封装在圆括号中

如果同一行放不下,可断为多行,后面每一行都可以第一个实参对其


8.6.条件语句

在圆括号和条件之间,不要有空格

如果能增强可读性,简短短条件语句允许写一行,并使用{}包围,只有当语句简单并且没有使用else子句时使用


8.7.循环和switch语句

switch语句可以使用大括号分段,空循环应使用{}或continue

如果有不满足case条件的枚举值,switch应该总是包含一个default,如果default永远指向不到,简单的加条assert


8.8.指针和引用表达式

句点或箭头前后不要有空格,指针/地址操作符(*,&)之后不能有空格

声明指针变量或参数时,星号与类型紧挨


8.9.布尔表达式

如果布尔表达式超过标准行宽,断行方式要统一:

if (this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another & last_one) 
{
  ...
}

8.10.函数返回值

return 表达式中不要用圆括号包围

8.11.变量及数组初始化

用=或()均可

int x = 3;
int x(3);
string name("Some Name");
string name = "Some Name";

8.12.预处理指令

即使预处理指令位于缩进代码块中,指令也应该从行首开始


8.13.类格式

所有基类名应在80列限制下尽量与子类名放在同一行

关键词public protected private 要缩进1个空格,除了第一个关键词外,其他关键词前要空一行,关键词后不要留空行


8.14.初始化列表


8.15.名字空间格式化

名字空间内容不缩进


8.16.水平留白

水平留白的使用因地制宜,永远不要在行尾添加没意义的留白


8.17.垂直留白

垂直留白越少越好,使得同屏可以显示的代码越多



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值