概述
文章目录
- 1.编码规范的作用
- 2.C++ 编码规范
- 2.1 命名原则
- 2.2 函数
- 2.3 类的设计申明
- 2.4 表达式和控制流程
- 2.5 异常处理
- 2.6 头文件
- 2.7 性能
- 2.8 继承
- 2.9 内存分配和释放
- 2.10 操作符
- 2.11 类型转换
- 2.12 编译
- 2.13 初始化和清除
- 2.14 重载
- 2.15 友元
- 2.16 模板
- 2.17 宏
- 2.18 代码格式
- 2.19 注释
- 3.总结
- 参考文献
《C++高级进阶教程》就编码规范作了如下叙述。
1.编码规范的作用
对于编程人员,良好的编程风格是提高程序可靠性和效率非常重要的手段。而编码规范就是对编程风格最好的约束保障。
严格遵守编码规范方便代码的交流和维护,利于提高代码的简洁性,稳定性和效率。
2.C++ 编码规范
C++ 的编码规范涉及到程序设计的方方面面,不是三言两语就可以描述清楚的。下面给出一些具体的编码规范,仅供参考,它说明了编码规范可能拥有的形式。
2.1 命名原则
- 减少匿名命名空间级标识符
- 命名时避免使用国际组织占用的格式
- 名字要本着清楚、简单的原则
- 尽量用可发音的名字
- 尽量用英文命名
- 尽量选择通用词汇并贯穿始终
- 避免用模棱两可、晦涩或不标准的缩写
- 避免使用会引起误解的词汇
- 减少名字中的冗余信息
- 建议起名尽量通俗,太专一会限制以后的扩展
- 名字最好尽可能精确地表达其内容
- 避免名字中出现形状混淆的字母或数字
- 命名类和成员使得“object.method()”有意义
- 类和对象名应是名词
- 实现行为的类成员函数名应是动词
- 类的存取和查询成员函数名应是名词或形容词
- 变量名应是名词
- 布尔型的名字要直观
- 避免局部名和外层的名字冲突
- 用 a、an、any 区分重名(参数)
- 模板类型名应有意义
此外,经典命名规则主要有:
(1)匈牙利命名法。该命名法是在每个变量名的前面加上若干表示数据类型的字符。基本原则是:变量名=属性+类型+对象描述。如 i 表示 int,所有 i 开头的变量命都表示 int 类型。s 表示string 类型,所有变量命以 s 开头的都表示 string 类型变量。
(2)小驼峰命名法,指混合使用大小写字母来构成变量和函数的名字,因首字母为小写且看上去像驼峰,因此而得名,如 userName。
(3)大驼峰命名法,又名帕斯卡命名法。因首字母大写且看上去像驼峰,因此而得名,如 UserName,常用于类名称。
大家可以根据自己的项目类型,选择一个命名规则作为自己的命名方法。
2.2 函数
- 一定要做到先定义后使用
- 函数原型申明放在一个头文件中
- 函数无参数一定要用void标注
- 对于内置类型参数应传值(除非函数内部要对其修改)
- 对于非内置类型参数应传递引用(首选)或指针
- 避免使用参数不确定的函数
- 若不得不适用参数不确定的函数,用< stdarg.h>提供的方法
- 避免函数的参数过多。
- 尽量保持函数只有唯一出口。
- 显式定义返回类型
- (非void)任何情况都要有返回值
- 若函数返回状态,尝试用枚举作类型
- 返回指针类型的函数应该用NULL 表示失败
- 函数尽量返回引用(而不是值)
- 若必须返回值,不要强行返回引用
- 当函数返回引用或指针时,用文字描述其有效期
- 禁止成员函数返回成员(可读写)的引用或指针
- 重复使用的代码用函数替代
2.3 类的设计申明
- 类应是描述一组对象的集合
- 类成员变量应是私有的(private)
- 保持对象状态信息的持续性
- 提高类内聚合度
- 降低类间的耦合度
- 努力使类的接口少而完备
- 保持类的不同接口在实现原则上的一致性
- 避免为每个类成员提供访问函数
- 不要在类定义时提供成员函数体
- 函数声明(而不是实现)时定义参数的缺省值
- 恰当选择成员函数、全局函数和友元函数
- 防范、杜绝潜在的二义性
- 显式禁止编译器自动生成不需要的函数
- 当遇到错误时对象应该应对有度
- 用嵌套类的方法减少匿名命名空间类的数量
2.4 表达式和控制流程
- 让表达式直观
- 避免在表达式中用赋值语句
- 不能将枚举类型进行运算后再赋给枚举变量
- 避免对浮点类型做等于或不等于判断
- 尝试用范围比较代替精确比较
- 范围用包含下限不包含上限方式表示
- 尽量不用 goto 语句
- 在循环过程中不要修改循环计数器
2.5 异常处理
- 确保代码在异常出现时能正确处理
- 正确注释代码的异常处理能力
- 减少不必要的异常处理
- 不要利用异常处理机制处理其他功能
- 注意模板类型可能会破坏异常处理的一些约定
- 确保异常发生后资源还能被回收
- 特别当心构造函数和析构函数发生异常
- 抛出的异常最好是一个对象
- 捕捉异常时绝不要先基类后派生类
- 捕捉异常时用引用
2.6 头文件
- 使用条件宏防止头文件多次被引用
- 确保公共头文件的自足性
- 只引用需要的头文件
- 引用头文件的顺序按照 Google C++ 标准
- 引用时需要用绝对路径
- 将函数库放在一个单独的目录下引用
- 不要在头文件中定义常量/变量
- 任何声明若被多个源文件引用则应在一个头文件中
- 头文件中尽量避免包含其他的头文件
2.7 性能
- 使用性能追踪分析工具
- 不要用移位代替乘除运算
- 如无必要,不要用非 int 的整型类型
- 不要使用关键字 register
- 避免在循环体内部定义对象
- 减少代价很高的对象拷贝
- 减少临时对象
- 注意大尺寸对象数组
- 返回对象(值)的优化
- 前缀 ++ 和 – 的效率更高
- 恰当使用递归
- 恰当地使用 inline 函数
- 虚函数和虚继承效率会有一点损失
- 如果合理,使用编译器生成的函数
- 如果合理,构造直传类
- 关于缓存(cache)类成员
- 关于标准库的性能
- 懂得偷懒
- 懂得勤快
- 80-20原则
2.8 继承
- 公共继承(public inheritance)意味着“派生类是基类”
- 关于“有”和“由…实现”
- 关于继承和模板(template)的区别
- 关于继承接口和继承实现
- 限制继承的层数
- 继承树上非叶子节点的类应是虚基类
- 显式提供继承和访问修饰:public、protected 或private
- 显式指出继承的虚函数
- 基类析构函数(destructor)首选是虚函数
- 绝不要重新定义(继承来的)非虚函数
- 绝不要重新定义缺省参数值
- 不要将基类强制转换成派生类
- 关于 C++ 中的分支用法选择
- 慎用多重继承
- 所有多重继承的基类析构函数都应是虚函数
2.9 内存分配和释放
- 用 new、delete 取代 malloc、calloc 、realloc 和 free
- new、delete 和 new[]、delete[] 要成对使用
- 确保所有 new 出来的东西适时被 delete 掉
- 谁申请谁释放
- 当对象消亡时确保指针成员指向的系统堆内存全部被释放
- 自定义类的 new/delete 操作符一定要符合原操作符的行为规范
- 自定义类的new 操作符一定要自定义类的delete 操作符
- 当所指的内存被释放后,指针应有一个合理的值
- 记住给字符串结束符申请空间
2.10 操作符
- 遵守操作符原本的含义,不要创新
- 确保自定义操作符能和其他操作符混合使用
- 区分作为成员函数和作为友元的操作符
- 尽量使用前缀操作符
- 确保相关的一组操作符行为统一
- 绝不要自定义 operator&&()、operator||() 和 operator,()
2.11 类型转换
- 尽量避免强制类型转换
- 如果不得不做类型转换,尽量用显式方式
- 使用新型的类型转换并确保选择正确
- 用虚函数方式取代dynamic_cast
- 自定义类最好提供显式而不是隐式转换函数
- 用关键字explicit 防止单参数构造函数的类型转换功能
- 限制隐式类型转换的类型数
- 避免多个函数提供相同的类型转换
2.12 编译
- 关注编译时的警告(warning)错误
- 把问题尽量暴露在编译时而不是运行时
- 减少文件的依赖程度
- 减少编译时间
- 透彻研究编译器
2.13 初始化和清除
- 声明后就初始化强于使用前才初始化
- 初始化要彻底
- 确保每一个构造函数都实现完全的初始化
- 尽量使用初始化列表
- 初始化列表要按成员声明顺序初始化它们
- 构造函数没结束,对象就没有构造出来
- 不要用构造函数初始化静态成员
- 拷贝构造函数和赋值函数尽量用常量参数
- 让赋值函数返回当前对象的引用
- 在赋值函数中防范自我赋值
- 拷贝和赋值要确保彻底
- 关于构造函数、析构函数、赋值函数、相等或不等函数的格式
- 为大多数类提供缺省和拷贝构造函数、析构函数、赋值函数、相等函数
- 只有在有意义时才提供缺省构造函数
- 包含资源管理的类应自定义拷贝构造函数、赋值函数和析构函数
- 拷贝构造函数、赋值函数和析构函数要么全自定义,要么全生成
- 类应有自己合理的拷贝原则:或浅拷贝或深拷贝
- 若编译时会完全初始化,不要给出数组的尺寸
- 将循环索引的初值定在循环点附近
- 确保全局变量在使用前被初始化
2.14 重载
- 仔细区分带缺省值参数的函数和重载函数
- 确保重载函数的所有版本有共同的目的和相似的行为
- 避免重载在指针和整型类型上
- 尽量避免重载在模板类型上
2.15 友元
- 少用友元
- 减少拥有友元特权的个数
2.16 模板
- 使用模板如果有限制条件一定要在注释和文档中描述清楚
- 模板类型应传引用/指针而不是值
- 注意模板编译的特殊性
2.17 宏
- 彻底用常量替代类似功能的宏
- 代码中的数值应由一个有意义的标识符代替
- 若宏值多于一项,一定要使用括号
- 不要用分号结束宏定义
- 彻底用 inline 函数替代宏函数
- 函数宏的每个参数都要括起来
- 不带参数的宏函数也要定义成函数形式
- 用 {} 将函数宏的函数体括起来
- 彻底用 typedef 代替宏定义新类型
- 不要在公共头文件中定义宏
- 不要用宏改写语言
2.18 代码格式
- 水平缩进每次用两个空格或一个 Tab
- 不要在引用操作符前后加空格
- 不要在单目操作符和其操作对象间加空格
- 不要在 :: 前后加空格
- 文件中的主要部分用空行分开
- 函数间要用空行分开
- 用空行将代码按逻辑片断划分
- 花括号 {} 要单独占一行
- 花括号中没有或只有一条语句时也不省略花括号
- 不要在一行中放多于一条语句
- 语句 switch 中的每个 case 各占一行
- 语句 switch 中的 case 按字母顺序排列
- 为所有 switch 语句提供 default 分支
- 若某个 case 不需要 break 一定要加注释声明
- 变量定义应集中放置、各占一行,并按字母顺序排列
- 定义指针和引用时 * 和 & 紧跟类型
- 按编译器解析顺序放置变量声明的修饰符
- 函数名和左括号间不要空格
- 声明函数时给出参数的名字,除非没有用处
- 类成员变量和函数按字母顺序排列
- 用带颜色的编辑器
2.19 注释
- 用英语写注释
- 确保注释完善你的代码,而不是重复你的代码
- 注释用词要精确,简单、清楚、切中要害,不能有二义性
- 注释中的术语要通用
- 注释中避免引用容易变化的信息
- 确保所有注释随代码及时更新
- 注释不具备约束使用者行为的能力
- 注释不要嵌套
- 行末注释尽量对齐
- 减少不必要的单独占一行的注释
- 对每个 #else 或 #endif 给出行末注释
- 对每个引用的头文件给出行末注释
- 对每个空循环体给出确认性注释
3.总结
要想写出优秀的 C++代码有很多注意点,远远不是上面这些规则所能完全囊括的。并且,这里罗列的编码规范可能与你曾经见过的一些编码规范有所出入,这很正常。所以,如果你相信自己的代码是简洁高效稳定的,不必拘泥与这些特定的编码规范。编码规范的灵活是隐藏在编码规范之后所要达到的真正目的。
参考文献
陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.C11.5关于编码规范.P382-384
最后
以上就是有魅力萝莉为你收集整理的C++ 编码规范建议1.编码规范的作用2.C++ 编码规范3.总结参考文献的全部内容,希望文章能够帮你解决C++ 编码规范建议1.编码规范的作用2.C++ 编码规范3.总结参考文献所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复