文档章节

[转]C/C++编码规范总结

 四彩
发布于 2016/02/04 17:51
字数 3708
阅读 104
收藏 17
点赞 2
评论 0

一、文件排版方面

1.包含头文件

1.1 先系统头文件,后用户头文件。

1.2 系统头文件,稳定的目录结构,应采用包含子路径方式。

1.3 自定义头文件,不稳定目录结构,应在dsp中指定包含路径。

1.4 系统头文件应用:#include <xxx.h>

1.5 自定义同文件应用:#include "xxx.h"

1.6 只引用需要的头文件。

2.h和cpp文件

2.1 头文件命名为*.h,内联文件命名为*.inl;C++文件命名为*.cpp

2.2 文件名用大小写混合,或者小写混合。例如DiyMainview.cppinfoview.cpp。不要用无意义的名称:例如XImage.cppSView.cppxlog.cpp

2.3 头文件除了特殊情况,应使用#ifdef控制块。

2.4 头文件#endif应采用行尾注释。

2.5 头文件,首先是包含代码块,其次是宏定义代码块,然后是全局变量,全局常量,类型定义,类定义,内联部分。

2.6 CPP文件,包含指令,宏定义,全局变量,函数定义。

3.文件结构

3.1 文件应包含文件头注释和内容。

3.2 函数体类体之间原则上用2个空行,特殊情况下可用一个或者不需要空行。

4.空行

4.1 文件头、控制块,#include部分、宏定义部分、class部分、全局常量部分、全局变量部分、函数和函数之间,用两个空行。

二、注释方面

1.文件头注释

1.1 作者,文件名称,文件说明,生成日期(可选)

2.函数注释

2.1 关键函数必须写上注释,说明函数的用途。

2.2 特别函数参数,需要说明参数的目的,由谁负责释放等等。

2.3 除了特别情况,注释写在代码之前,不要放到代码行之后。

2.4 对每个#else#endif给出行末注释。

2.5 关键代码注释,包括但不限于:赋值,函数调用,表达式,分支等等。

2.6 善未实现完整的代码,或者需要进一步优化的代码,应加上 // TODO ...

2.7 调试的代码,加上注释 // only for DEBUG

2.8 需要引起关注的代码,加上注释 // NOTE ...

2.9 对于较大的代码块结尾,如for,while,do等,可加上 // end for|while|do

三、命名方面

1.原则

1.1 同一性:在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。

1.2 标识符组成:标识符采用英文单词或其组合,应当直观且可以拼读,可望文知意,用词应当准确,避免用拼音命名。

1.3 最小化长度 && 最大化信息量原则:在保持一个标识符意思明确的同时,应当尽量缩短其长度。

1.4 避免过于相似:不要出现仅靠大小写区分的相似的标识符,例如"i""I""function""Function"等等。

1.5 避免在不同级别的作用域中重名:程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。

1.6 正确命名具有互斥意义的标识符:用正确的反义词组命名具有互斥意义的标识符,如:"nMinValue" 和 "nMaxValue""GetName()" 和"SetName()" ….

1.7 避免名字中出现数字编号:尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。

2.T,C,M,R类

2.1 T类表示简单数据类型,不对资源拥有控制权,在析构过程中没有释放资源动作。

2.2 C表示从CBase继承的类。该类不能从栈上定义变量,只能从堆上创建。

2.3 M表示接口类。

2.4 R是资源类,通常是系统固有类型。除了特殊情况,不应在开发代码中出现R类型。

3.函数名

3.1 M类的函数名称应采用HandleXXX命名,例如:HandleTimerEvent;不推荐采用java风格,例如 handleTimerEvent;除了标准c风格代码,不推荐用下划线,例如,handle_event

3.2 Leave函数,用后缀L。

3.3 Leave函数,且进清除栈,用后缀LC。

3.4 Leave函数,且删除对象,用后缀LD。

4.函数参数

4.1 函数参数用a作为前缀。

4.2 避免出现和匈牙利混合的命名规则如apBuffer名称。用aBuffer即可。

4.3 函数参数比较多时,应考虑用结构代替。

4.4 如果不能避免函数参数比较多,应在排版上可考虑每个参数占用一行,参数名竖向对齐。

5.成员变量

5.1 成员变量用m最为前缀。

5.2 避免出现和匈牙利混合的命名规则如mpBuffer名称。用mBuffer即可。

6.局部变量

6.1 循环变量和简单变量采用简单小写字符串即可。例如,int i;

6.2 指针变量用p打头,例如void* pBuffer;

7.全局变量

7.1 全局变量用g_最为前缀。

8.类名

8.1 类和对象名应是名词。

8.2 实现行为的类成员函数名应是动词。

8.3 类的存取和查询成员函数名应是名词或形容词。

9.风格兼容性

9.1 对于移植的或者开源的代码,可以沿用原有风格,不用C++的命名规范。

四、代码风格方面

1.Tab和空格

1.1 每一行开始处的缩进只能用Tab,不能用空格,输入内容之后统一用空格。除了最开始的缩进控制用Tab,其他部分为了对齐,需要使用空格进行缩进。这样可以避免在不同的编辑器下显示不对齐的情况。

1.2 在代码行的结尾部分不能出现多余的空格。

1.3 不要在"::","->","."前后加空格。

1.4 不要在",",";"之前加空格。

2.类型定义和{

2.1 类,结构,枚举,联合:大括号另起一行

3.函数

3.1 函数体的{需要新起一行,在{之前不能有缩进。

3.2 除了特别情况,函数体内不能出现两个空行。

3.3 除了特别情况,函数体内不能宏定义指令。

3.4 在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。

3.5 在头文件定义的inline函数,函数之间可以不用空行,推荐用一个空行。

4.代码块

4.1 "if"、"for"、"while"、"do"、"try"、"catch" 等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加 "{ }" 。这样可以防止书写和修改代码时出现失误。

4.2 "if"、"for"、"while"、"do"、"try"、"catch" 的括号和表达式,括号可紧挨关键字,这样强调的是表达式。

5.else

5.1 if语句如果有else语句,用 } else { 编写为一行,不推荐用 3 行代码的方式。

6.代码行

6.1 一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。

6.2 多行变量定义,为了追求代码排版美观,可将变量竖向对齐。

6.3 代码行最大长度宜控制在一定个字符以内,能在当前屏幕内全部可见为宜。

7.switch语句

7.1 case关键字应和switch对齐。

7.2 case子语句如果有变量,应用{}包含起来。

7.3 如果有并列的类似的简单case语句,可考虑将case代码块写为一行代码。

7.4 简单的case之间可不用空行,复杂的case之间应考虑用空行分割开。

7.5 case字语句的大括号另起一行,不要和case写到一行。

7.6 为所有switch语句提供default分支。

7.7 若某个case不需要break一定要加注释声明。

8.循环

8.1 空循环可用 for( ;; ) 或者 while( 1 ) 或者 while( true )

9.类

9.1 类继承应采用每个基类占据一行的方式。

9.2 单继承可将基类放在类定义的同一行。如果用多行,则应用Tab缩进。

9.3 多继承在基类比较多的情况下,应将基类分行,并采用Tab缩进对齐。

9.4 重载基类虚函数,应在该组虚函数前写注释 // implement XXX

9.5 友元声明放到类的末尾。

10.宏

10.1 不要用分号结束宏定义。

10.2 函数宏的每个参数都要括起来。

10.3 不带参数的宏函数也要定义成函数形式。

11.goto

11.1 尽量不要用goto。

五、类型

  1. 定义指针和引用时*&紧跟类型。

  2. 尽量避免使用浮点数,除非必须。

  3. typedef简化程序中的复杂语法。

  4. 避免定义无名称的类型。例如:typedef enum { EIdle, EActive } TState;

  5. 少用union,如果一定要用,则采用简单数据类型成员。

  6. enum取代(一组相关的)常量。

  7. 不要使用魔鬼数字。

  8. 尽量用引用取代指针。

  9. 定义变量完成后立即初始化,勿等到使用时才进行。

  10. 如果有更优雅的解决方案,不要使用强制类型转换。

六、表达式

  1. 避免在表达式中用赋值语句。

  2. 避免对浮点类型做等于或不等于判断。

  3. 不能将枚举类型进行运算后再赋给枚举变量。

  4. 在循环过程中不要修改循环计数器。

  5. 检测空指针,用 if( p )

  6. 检测非空指针,用 if( ! p )

七、函数

1.引用

1.1 引用类型作为返回值:函数必须返回一个存在的对象。

1.2 引用类型作为参数:调用者必须传递一个存在的对象。

2.常量成员函数

2.1 表示该函数只读取对象的内容,不会对对象进行修改。

3.返回值

3.1 除开void函数,构造函数,析构函数,其它函数必须要有返回值。

3.2 当函数返回引用或指针时,用文字描述其有效期。

4.内联函数

4.1 内联函数应将函数体放到类体外。

4.2 只有简单的函数才有必要设计为内联函数,复杂业务逻辑的函数不要这么做。

4.3 虚函数不要设计为内联函数。

5.函数参数

5.1 只读取该参数的内容,不对其内容做修改,用常量引用。

5.2 修改参数内容,或需要通过参数返回,用非常量应用。

5.3 简单数据类型用传值方式。

5.4 复杂数据类型用引用或指针方式。

八、类

1.构造函数

1.1 构造函数的初始化列表,应和类的顺序一致。

1.2 初始化列表中的每个项,应独占一行。

1.3 避免出现用一个成员初始化另一个成员。

1.4 构造函数应初始化所有成员,尤其是指针。

1.5 不要在构造函数和析构函数中抛出异常。

2.纯虚函数

2.1 M类的虚函数应设计为纯虚函数。

3.构造和析构函数

3.1 如果类可以继承,则应将类析构函数设计为虚函数。

3.2 如果类不允许继承,则应将类析构函数设计为非虚函数。

3.3 如果类不能被复制,则应将拷贝构造函数和赋值运算符设计为私有的。

3.4 如果为类设计了构造函数,则应有析构函数。

4.成员变量

4.1 尽量避免使用mutableVolatile

4.2 尽量避免使用公有成员变量。

5.成员函数

5.1 努力使类的接口少而完备。

5.2 尽量使用常成员函数代替非常成员函数,const函数

5.3 除非特别理由,绝不要重新定义(继承来的)非虚函数。(这样是覆盖,基类的某些属性无初始化)

6.继承

6.1 继承必须满足IS-A的关系,HAS-A应采用包含。

6.2 虚函数不要采用默认参数。

6.3 除非特别需要,应避免设计大而全的虚函数,虚函数功能要单一。

6.4 除非特别需要,避免将基类强制转换成派生类。

7.友元

7.1 尽量避免使用友元函数和友元类。

九、错误处理

  1. 申请内存用new操作符。

  2. 释放内存用delete操作符。

  3. newdeletenew[]delete[]成对使用。

  4. 申请内存完成之后,要检测指针是否申请成功,处理申请失败的情况。

  5. 谁申请谁释放。优先级:函数层面,类层面,模块层面。

  6. 释放内存完成后将指针赋空,避免出现野指针。

  7. 使用指针前进行判断合法性,应考虑到为空的情况的处理。

  8. 使用数组时,应先判断索引的有效性,处理无效的索引的情况。

  9. 代码不能出现编译警告。

  10. 使用错误传递的错误处理思想。

  11. 卫句风格:先处理所有可能发生错误的情况,再处理正常情况。

  12. 嵌套do-while(0)宏:目的是将一组语句变成一个语句,避免被其他if等中断。

十、性能

  1. 使用前向声明代替#include指令。Class M;

  2. 尽量用++i代替i++。即用前缀代替后缀运算。

  3. 尽量在for循环之前,先写计算估值表达式。

  4. 尽量避免在循环体内部定义对象。

  5. 避免对象拷贝,尤其是代价很高的对象拷贝。

  6. 避免生成临时对象,尤其是大的临时对象。

  7. 注意大尺寸对象数组。

  8. 80-20原则。

十一、兼容性

  1. 遵守ANSI C和ISO C++国际标准。

  2. 确保类型转换不会丢失信息。

  3. 注意双字节字符的兼容性。

  4. 注意运算溢出问题。

  5. 不要假设类型的存储尺寸。

  6. 不要假设表达式的运算顺序。

  7. 不要假设函数参数的计算顺序。

  8. 不要假设不同源文件中静态或全局变量的初始化顺序。

  9. 不要依赖编译器基于实现、未明确或未定义的功能。

  10. 将所有#include的文件名视为大小写敏感。

  11. 避免使用全局变量、静态变量、函数静态变量、类静态变量。在使用静态库,动态库,多线程环境时,会导致兼容性问题。

  12. 不要重新实现标准库函数,如STL已经存在的。


转的,原文地址http://developer.51cto.com/art/201601/504912.htm

© 著作权归作者所有

共有 人打赏支持
粉丝 25
博文 49
码字总数 77226
作品 0
茂名
C语言/C++编程学习未来之路

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 03/30 ⋅ 0

公开课-C++学习路线实战导引:从0开始到操作系统内核开发

公开课观看办法: 加入到51CTO学院C++交流群 431187655 在群中直播 课程简介 从整个IT行业角度出发, C/C++技术定位于后端服务与系统级软件研发工作,这意味着C/C++的从业人员应当精通从win...

夏曹俊 ⋅ 06/13 ⋅ 0

Java程序员如何高效而优雅地入门C++

Java程序员如何高效而优雅地入门Cpp,由于工作需要,需要用C++写一些模块。关于C++ 的知识结构,虽说我有过快速学习很多新语言的经验,但对于C++ 我也算是老手,但也还需要心生敬畏,本文会从...

小欣妹妹 ⋅ 04/23 ⋅ 0

C语言/C++程序员编程学习自信心曲线图

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 05/10 ⋅ 0

C语言/C++编程基础入门学习重要知识之i++和++i的区别

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 03/17 ⋅ 0

C、C++、Java、JavaScript、PHP、Python分别用来开发什么?

C、C++、Java、JavaScript、PHP、Python分别用来开发什么? 2018-05-25 11:47编辑: 游星啊分类:程序人生来源:代码湾 开发程序人生C 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发...

游星啊 ⋅ 05/25 ⋅ 0

C语言/C++编程学习强势之处的体现

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 05/12 ⋅ 0

VS2010/MFC编程入门教程之目录和总结(鸡啄米)

鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够。以此教程的知识为基础,学习VS2010/MFC较为深入的内容已非难事...

weixin_40647819 ⋅ 05/23 ⋅ 0

什么是 C 和 C ++ 标准库?

简要介绍编写C/C ++应用程序的领域,标准库的作用以及它是如何在各种操作系统中实现的。 我已经接触C++一段时间了,一开始就让我感到疑惑的是其内部结构:我所使用的内核函数和类从何而来? ...

oschina ⋅ 04/10 ⋅ 0

大神有话说之c++,还在迷茫的朋友可以来看一下

C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言。C++ 可运行于多种平台上,如 Window...

悟空_b201 ⋅ 05/30 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JavaScript零基础入门——(八)JavaScript的数组

JavaScript零基础入门——(八)JavaScript的数组 欢迎大家回到我们的JavaScript零基础入门,上一节课我们讲了有关JavaScript正则表达式的相关知识点,便于大家更好的对字符串进行处理。这一...

JandenMa ⋅ 今天 ⋅ 0

sbt网络问题解决方案

转自:http://dblab.xmu.edu.cn/blog/maven-network-problem/ cd ~/.sbt/launchers/0.13.9unzip -q ./sbt-launch.jar 修改 vi sbt/sbt.boot.properties 增加一个oschina库地址: [reposit......

狐狸老侠 ⋅ 今天 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 今天 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 今天 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

聊聊spring cloud的RequestRateLimiterGatewayFilter

序 本文主要研究一下spring cloud的RequestRateLimiterGatewayFilter GatewayAutoConfiguration @Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMi......

go4it ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部