编码原则实例------c++程序设计原理与实践(进阶篇)
编码原则:
- 一般原则
- 预处理原则
- 命名和布局原则
- 类原则
- 函数和表达式原则
- 硬实时原则
- 关键系统原则
(硬实时原则、关键系统原则仅用于硬实时和关键系统程序设计)
(严格原则都用一个大写字母R及其编号标识,而推荐原则都用小写字母r及其编号标识,对于前者程序员必须严格遵守,而后者则偶尔可以不遵守)
1、一般原则
R100:任何函数和类的代码规模都不应超过200行(不包括注释)。
原因:长的函数和类会更复杂,因而难以理解和测试。
r101:任何函数和类都应该能完全显示在一屏上,并完成单一的逻辑功能。
原因:如果程序员只能看到函数或类的一部分,就很可能漏掉错误的部分。如果一个函数试图完成多个功能,与单功能的函数相比,其规模就可能很大,而且会更复杂。
R102:所以代码都应该遵守ISO/IEC 14882:2011(E)C++标准。
原因:在ISO/IEC 14882标准之上的扩展金额变形可能会不稳定,定义不明确,而且可能影响移植性。
2、预处理原则
R200:除了用于源码控制的#ifdef和#ifndef之外,不要使用宏。
原因:宏不遵守定义域和类型规则,而且使代码变得更不清晰、不易读。
R201:#include 只能用于包含头文件(*.h)。
原因:#include 用于访问接口的声明而非实现细节。
R202:所以的#incldue语句都应位于任何非预处理声明之前。
原因:如果#include语句位于程序中间,就很可能被阅读程序的人忽略,而且容易导致程序不同部分对名字的解析不一致。
R203:头文件(*.h)不应包含非常量变量的定义或非内联、非模板函数定义。
原因:头文件应该包含接口声明而非实现细节。但是,常量常被看作接口的一部分;出于性能的考虑,一些非常简单的函数应该作为内联函数(因此应该放在头文件中);而当前的编译器要求完整的模板定义都放在头文件中。
3、命名和布局原则
R300:应该使用缩进,并且在一个源码文件中缩进风格应该一致。
原因:可读性和代码风格。
R301:每条新语句都另起一行。
原因:可读性。
例子:
- int a=7;x=a+7;f(x,9); //违反
- int a=7;
- x=a+7;
- f(x,9); //正确
例子:
- if(p<q)cout<<*p; //违反
- if(p<q)
- cout<<*p; //正确
R302:标识符的名字应该都具有描述性。
标识符可以包含常见的缩写和字头缩略。
如果x、y、i、j是按习惯方式使用,可以认为是有描述性的。
使用下划线风格(number_of_elements)而不是字头缩略风格(numberOfElement)。
不要使用匈牙利命名法。
类型、模板和命名空间的命名都以大写字母开头。
避免过长的名字。
例子:Device_driver 和Buffer_poor。
原因:可读性。
注意:c++标准规定,以下划线开头的标识符留作语言实现所用,因此在用户程序中应被禁止。
例外:调用经过认证的库,来自库中名字是可以使用的。
R303:标识符不能只在以下方面不同:
- 大小写不同;
- 只相差下划线;
- 只是字母O、数字0或字母D间的替换;
- 只是字母I、数字1后字母l之间的替换;
- 只是字母S和数字5之间的替换;
- 只是字面Z和字数2之间的替换;
- 只是字母与n和字母h直接的替换。
例子:Head和head //违反
原因:可读性。
R304:标识符不能只包含大写字母和下划线。
例子:BLUE和BLUE_CHEESE //违反
原因:全部大写字母的标识符被广泛用于宏名,可能用于经过认证的库中的#include文件,而不应该用于客户程序。
例外:宏名用于保护#include不被重复包含。
4、函数和表达式原则
r400:内层循环的标识符和外层循环的标识符不应重名。
原因:可读性和代码风格。
例子:
- int var=9;{int var=7;++var} //违反:var重名
R401:声明的作用域应该尽量小。
原因:保持变量的初始化和使用尽量靠近,以降低混乱的可能性;令离开作用域的变量释放其资源。
R402:所以变量都要初始化。
例子:
- int var; //违反:var没有初始化
原因:未初始化的变量通常是错误之源。
例外:如果数组或容器会立即从输入接受数据,则不必初始化。
注意:许多类型,例如vector和string,有默认的构造函数来完成初始化。
R403:不应使用类型转换。
原因:类型转换是错误之源。
例外:dynamic_cast可以使用。
例外:新风格的类型转换可以使用,用来将硬件地址转换为指针,或者将从程序外部(如GUI库)获取的void*转换为恰当类型的指针。
R404:函数接口中不应使用内置数组类型,即,如果一个函数参数是指针,那么它必须指向单个元素。如果希望传递数组,应使用Array_ref。
原因:数组只能以指针方式传递,而元素数目无法附着其上,只能分开传递。而且,隐式的数组到指针的转换和派生类到基类的转换会引起内存错误。
5、类原则
R500:对于没有共有数据成员的类,用class声明。对没有私有数据成员的类,用struct声明。不要定义既有共有数据成员,又有私有数据成员的类。
原因:清晰性。
r501:如果类包含析构函数或者指针/引用类型的成员,必须为其定义恰当的或禁止(即,不能使用默认版本)拷贝构造函数和拷贝赋值运算符。
原因:析构函数通常会释放资源。对于具有析构函数或者指针和引用类型的类,默认拷贝语义几乎不可能”做正确的事“。
R502:如果类包含虚函数,那么它必须具有虚析构函数。
原因:虚函数可以通过基类接口使用,通过基类接口访问对象的函数可能会删除对象,派生类必须有某种机制(析构函数)来进行清理工作。
R503:接受单一参数的构造函数必须显式声明。
原因:避免奇怪的隐式类型转换。
6、硬实时原则
R800:不应使用异常。
原因:异常不可预测。
R801:new只能在初始化时使用。
原因:不可预测。
例外:可以用定址的new从栈中分配内存。
R802:不应使用delete。
原因:不可预测,可能会引起碎片。
R803:不应使用dynamic_cast。
原因:不可预测(假定使用普通方法实现的)。
R804:不应使用标准库容器,std::array除外
原因:不可预测(假定是用普通方法实现的)。
7、关键系统原则
R900:递增和递减运算不能作为子表达式。
例子:
- int x=v[++i]; //违反
- ++i;
int x=v[i]; //正确
原因:可能会被漏掉。
R901:代码不应依赖于算法表达式优先级之下的优先级规则。
例子:
- x=a*b+c; //正确
例子:
- if(a<b||c<=d) //违反:应加上括号(a<b)和(c<=d)
原因:c/c++基础较差的程序员写出的代码中常常会有优先级混乱的情况。
c++程序设计原理与实践(进阶篇)
编码原则实例------c++程序设计原理与实践(进阶篇)的更多相关文章
- C++学习书籍推荐《C++程序设计原理与实践》下载
百度云及其他网盘下载地址:点我 编辑推荐 <C++程序设计原理与实践>是经典程序设计思想与C++开发实践的完美结合,是C++之父回归校园后对C++编程原理和技巧的全新阐述.书中全面地介绍了 ...
- 数值限制------c++程序设计原理与实践(进阶篇)
每种c++的实现都在<limits>.<climits>.<limits.h>和<float.h>中指明了内置类型的属性,因此程序员可以利用这些属性来检 ...
- 有符号数和无符号数------c++程序设计原理与实践(进阶篇)
有符号数与无符号数的程序设计原则: 当需要表示数值时,使用有符号数(如 int). 当需要表示位集合时,使用无符号数(如unsigned int). 有符号数和无符号数混合运算有可能会带来灾难性的后果 ...
- 函数形参为基类数组,实参为继承类数组,下存在的问题------c++程序设计原理与实践(进阶篇)
示例: #include<iostream> using namespace std; class A { public: int a; int b; A(int aa=1, int bb ...
- 函数返回值string与返回值bool区别------c++程序设计原理与实践(进阶篇)
为什么find_from_addr()和find_subject()如此不同?比如,find_from_addr()返回bool值,而find_subject()返回string.原因在于我们想说明: ...
- (c++11)随机数------c++程序设计原理与实践(进阶篇)
随机数既是一个实用工具,也是一个数学问题,它高度复杂,这与它在现实世界中的重要性是相匹配的.在此我们只讨论随机数哦最基本的内容,这些内容可用于简单的测试和仿真.在<random>中,标准库 ...
- 实现求解线性方程(矩阵、高斯消去法)------c++程序设计原理与实践(进阶篇)
步骤: 其中A是一个n*n的系数方阵 向量x和b分别是未知数和常量向量: 这个系统可能有0个.1个或者无穷多个解,这取决于系数矩阵A和向量b.求解线性系统的方法有很多,这里使用一种经典的方法——高斯消 ...
- bitest(位集合)------c++程序设计原理与实践(进阶篇)
标准库模板类bitset是在<bitset>中定义的,它用于描述和处理二进制位集合.每个bitset的大小是固定的,在创建时指定: bitset<4> flags; bitse ...
- gets()scanf()有害------c++程序设计原理与实践(进阶篇)
最简单的读取字符串的方式是使用gets(),例如: char a[12]; gets(a); 但gets()和scanf()是有害的,曾经有大约1/4的成功黑客攻击是由于gets()和它的近亲scan ...
随机推荐
- Java中静态变量、静态代码块、非静态代码块以及静态方法的加载顺序
在研究单例设计模式的时候,用到了静态变量和静态方法的内容,出于兴趣,这里简单了解一下这四个模块在类初始化的时候的加载顺序. 经过研究发现,它们的加载顺序为: 1.非静态代码块 2.静态变量或者静态代码 ...
- 解决:An internal error occurred during: "Launching New_configuration". Path for project must have only one segment.
问题: 点击运行时eclipse报错如下: An internal error occurred during: "Launching New_configuration". Pa ...
- js处理数值和日期本地化
js处理数值和日期本地化 const s = new Intl.NumberFormat('zh-cn'); s.format(111.111) // "111.111" cons ...
- 使用Handler类来更新UI
在android里面,我们经常要上网获取一些数据,然后更新UI,但获取数据是要时间的,如果在主线程里面直接使用获取数据的代码的话.整个activity就会卡在那,直至你获取到数据更新完UI才会加载完成 ...
- 手机发烫是为何—— App 电量测试定位方法
为什么要做电量测试 随着移动互联网的快速发展,手机的实用性.娱乐性越来越强.日常使用中发现,安装了应用后,即使不怎么使用,电量也会消耗很快.但如果恢复出场设置充满电后,手机可以待机很长时间.真相只有一 ...
- Oracle11g-BBED安装
oracle 11g中缺bbed包 下载地址: https://pan.baidu.com/s/19DVvIajarDjnynILNwQDWQ 密码:tmqt 1.BBED的安装 1.上传(sbbdp ...
- openark对MySQL进行Online_DDL
1.用oak对表sbtest1做添加字段和增加索引的Online DDL openark kit 提供一组小程序,用来帮助日常的 MySQL 维护任务,可代替繁杂的手工操作. 包括: oak-appl ...
- BMP格式详解
BMP格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Win ...
- 【原】Coursera—Andrew Ng机器学习—编程作业 Programming Exercise 2——逻辑回归
作业说明 Exercise 2,Week 3,使用Octave实现逻辑回归模型.数据集 ex2data1.txt ,ex2data2.txt 实现 Sigmoid .代价函数计算Computing ...
- libevent源码深度剖析八
libevent源码深度剖析八 ——集成信号处理 张亮 现在我们已经了解了libevent的基本框架:事件管理框架和事件主循环.上节提到了libevent中I/O事件和Signal以及Timer事件的 ...