C++编码规范

来源:互联网 发布:搜狗算法面试题 编辑:程序博客网 时间:2024/05/22 00:22

1. 文件及预处理器 Files and the preprocessor  
 
1.1 
变更日志如果有的话,请放在文件的尾部因为源程序文件的主要角色还是反 
    
映项目当前状态,不是反映变化过程
 
1.2 
在头文件中使用#include guards防止被include多次
    (
就是#ifndef xxx_hpp #define xxx_hpp #endif) 
 
1.3 
避免定义预处理的宏 特别是在头文件中(规则1.2例外),请使用enum,const,function 
    template 
等避免宏的定义
 
1.4 
源文件名一律小写 因为不同平台的文件大小写敏感不一样 
 
1.5 
源程序应该首先#include对应的头文件 确保每个头文件都可以单独被include,而不需 
    
要额外的头文件依赖
 
1.6 #include
一律出现在文件开头如果是头文件请放在#include guards 之后 
 
1.7 
尽量避免头文件依赖 如果某个头文件中需要用到某个类的引用或指针,那么只需要一 
    
forward declaration就足够了 
 
1.8 
使用相对#include路径目录结构最好和工程的namespace结构类似 
    (
这一点boost库做的很好)

 

2. 命名 Naming 
 
2.1 
命名,除了以下提到的规则之外,应当是"全部小写"并使用下划线分割单词.首字缩写 
    
的缩写词作为单词同等对待 
 
2.2 
模版形式参数命名 使用单词首字母大写形式InMixedCase 
 
2.3 Concept[
1]命名和2.2采用同样的命名方式 
 
2.4 
用完整的单词或词组命名 循环变量和遍历算子除外一个好名字比一段解释该名字 
    
含义的注释更好 
 
2.5 
避免简写和复合词 Iterator  Iter 短单词比被缩短的单词好 
 
2.6 
选择表示目的的名字 而不是表示实现的名字,比如定义一个已知设备列表  
    list<device>, 
命名为known_devices而不是device_list. 
 
2.7 
布尔变量和布尔函数应当是E文中的谓词短语 这样条件语句读起来就好像是E文中的 
    
条件句了if (buffer->is_empty())  
 
2.8 
具有side effect[2]的函数应当是E文中的动词短语 
 
2.9 
在命名中避免trademark 
 
2.10 
数据成员应具有m_前缀 
 
2.11 
短名字应当依照通用惯例i j k用于循环控制变量,p q用于指针和遍历子 
 
2.12 
描述对象状态的函数应当是名词短语 如得到container长度的函数应叫size() 
     
不是get_size() 
 
2.13 
预处理宏应尽量避免 无法避免的时候,它的命名应当是全大写形式,头文件中使用的 
     
宏要么就取一个奇长无比的名字,要么就在使用以后#undef(避免名字污染,呵呵
 
2.14 
禁止使用带有双下划线'__',或是以单下滑线'_'开头的名字

 

3. 表达式的间隔、各种括号 Expression spacing and bracketing 
 
3.1 
二目运算符 用空格将它和它的操作数分开 int b = a + 2 
 
3.2 
单目后缀运算符 不能有前导空格 f(),a[],i++ 
 
3.3 
单目前缀运算符 不能紧跟有空格 *p,!is_right 
 
3.4 ->
前后都不能有空格 
 
3.5 
使用位运算时请写全括号  
 
3.6 return
不是函数 不要对return的结果打上括号, throw也是一样 
 
3.7 
如果表达式要分开多行,请在某个运算符之前分行 这样下一行很明显能看出是上一行的继续 
    
int b = a 
              + 2; 

 

4.1 主名字空间或全局空间中的定义语句顶格 第二个嵌套的名字空间中的定义语句需要 
    
空两格 
 
4.2 
定义语句分行书写但缩进相同只用于以下情形 
      template<..>
语句 
      
被定义的类名或是函数名 
      
函数,语句,类定义时的'{','}'符号 
  
4.3 
函数的返回值和所属类名和函数名写在一行 
 
4.4 
连续的两个多行定义之间需要用空行隔开 
 
4.5 class bodies
中的变量定义需要缩进2-4个空格,类中的成员的多行定义需要进一步的 
    
缩进 
 
4.6 
函数定义的参数如要分开多行定义需要进一步的缩进... 
 
4.7 
多行定义和其他代码之间应该用空行隔开 
 
4.8 
存取权限说明符(public,private,protected) 在类的声明中缩进1个空格 
 
4.9 
模版实例化中忽略(类型参数之间的)空格 模版声明时可以适当(类型参数之间)加入空 
    
过于笨重的模版实例应该被typedef 

 

5. 块和语句的格式化 Block and statement formatting 
 
5.1 '{'
'}'单独占用一行 
 
5.2 '{'
'}'应和该块代码的前一行代码具有相同的缩进 
 
5.3 
块内的语句缩进4 
 
5.4 
缩进时使用空格,不要用TAB,否则不同的TAB长度会产生对齐的问题 
 
5.5 
附属的流程控制子语句使用单独的行 
    
不要这样写 if(...) do_something; 
 
5.6 
多行的附属子语句前后必须加'{''}' 
    
 
    if(...) 
    { 
        // one line 
        // another 
    } 
 
5.7 
如果if子句加了'{''}',else字句也要加,反过来也一样 
 
5.8 
如果同一语句的分行书写,从第二行开始需要缩进,至少2 

 

6. 声明和初始化 Declarations and initialization 
6.1 
一行只能声明一个名字 
 
6.2 
*,&和类型名放在一起不要和对象名放在一起(如写成int* p, 而不是int *p)[1]  
 
 
6.3 
等到有意义的初值出现时再初始化局部变量这样可以防止未被初始化的变量被使用 
 
6.4 
尽可能晚的定义局部变量 
 
6.5 
复用一个变量时不要出于不同的目的复用变量并不会节约资源,编译器知道一个变量 
    
什么时候没有用了相反复用变量会把读代码的人搞糊涂.  
 
6.6 
尽可能的使用const. 看的人清楚,用的人也明白,使用错误时编译器还能报错 
 
6.7 
const放在他修饰的基类型之后int const n = 5; 
 
1: 很多人会认为写成int* p是初学者的行为其实不然我认为原因是这样的虽然 
     *
号在语法上是p的修饰符但是在语意上却是类型int的修饰符,  如果同时按照6.1 
     
所说的去做,就不会出现int* p,q这样的错误 

 

7. 注释和文档 Comments and documentation 
 
7.1 
使用// 
 
7.2 
长注释应和代码分在不同的行 
 
7.3 
所有的函数接口必须写注释(除了拷贝构造函数运算符重载析构函数等), 描述 
    
信息包括 函数要求函数效果(特别是边际效应)... 
 
7.4 
函数的注释放在一处就好不用在声明和定义两边都写 
 
7.5 
注释所有的publicprotected成员函数的声明那些具有特定意义的函数如拷贝构 
    
造函数拷贝赋值运算符,析构函数就不用了 
 
7.6 
对于每一个虚函数在还没有被继承的地方注释  注释包括该函数会在何时被调用,  
    
如何被调用什么时候会需要重载它对于非纯虚函数写出它缺省实现的效果 
 
7.7 
作为类的public interface的一部分的自由函数的声明必须注视 
 
7.8 
所有其它函数(private的非虚函数在无名namespace中定义的函数)应该在定义的地 
    
方写下它的注释这是为了避免在头文件中留下实现细节的描述 
 
7.9 
在类的声明时尽量简单(不要留太多对使用这个类的用户无意义的信息在声明里
 
7.10 
在代码中的注释应当致力于解释为什么而不是怎么作好的注释并不是重复代码中 
     
显而易见的事实而是引起对代码中微妙的弱点的重视明白的代码常常是被注释所 
     
玷污了不过对于作者显而易见的东西对于读者来说常常是晦涩的一整段的注释要 
     
比逐行解释好的多
 
7.11 
使用正确的E文句子作注释要正确拼写首字大写带上标点 
 
7.12 
使用标准的C++词汇要写成member function而不是method, class template,  
     
不是template class, data member而不是attribute 
 
7.13 
写注释时符号名按照代码里的样式书写 符号名在句首同样保持小写, concept名无 
     
论何时出现都大写函数名后加上() 
 
7.14 
能够被publicprotected interface访问到的"类的不变式"[1]应该在类声明 
     
之前写好注释
     
实现细节中的不变式的规格说明应该写在类的实现之前
 
7.15 
使用'#if 0...#endif''//'注释代码,不要使用'/*...*/' 
     (
我想是因为/**/不支持嵌套注释吧#if 0...#endif可以嵌套
 
1: 关于类的不变式请看原文吧我实在不知道怎么解释这个概念我不懂 
     
简单的说应该是关于类的对象状态的一些断言吧在类的所有数据成员的所有可能 
     
的取值的笛卡尔积的集合中对象的可能达到的状态只是一个很小的子集如何描 
     
述这个子集使用类的不变式描述
     
个人观点.... 

 

8. 类的组织 Class organization 
8.1 
按照以下顺序组织类的定义 按照用户最为关心的顺序 
        Public type forward-declarations & typedefs  
        Public constructors & destructor  
        Public member functions  
        ----------------------------------------------------------- 
 
         
        Protected type forward-declarations & typedefs  
        Protected member functions  
        ----------------------------------------------------------- 
        Private type forward-declarations  
        Private member functions  
        Private data members  
 
8.2 
所有的数据成员定义为private, 禁止出现protected数据成员 
 
8.3 
友员只能访问成员函数 
 
8.4 
禁止在class body中进行函数定义(逛当!) 
 
8.5 
嵌套类的定义应当尽可能放在被嵌套的class body如果嵌套类属于实现细节,  
    
放入相应的源文件 
 
8.6 
复用public private protected关键字将不同类型的member分开如成员函数 
    
和数据成员 
 
8.7 
在继承类里就不要重复写virtual关键字了可以将它们的声明组织成一组 
 
8.8 
成员函数声明是不需要inline关键字的放在定义部分就足够了

原创粉丝点击