您的位置:首页 > 编程语言 > C语言/C++

高质量C&C++编程指南阅读笔记,让程序更好看!

2015-01-23 13:44 453 查看
一本不错的书,告诉你该如何布局C++程序使得自己更像一个专业程序员!
一 文件结构
1.1 版权和版本的声明
程序开头应有如下声明,如果是自己玩的程序可适当减少,但也应有足够信息提醒自己不至于若干年后再翻出来完全不知道这货是干什么的。
包含以下内容:
(1)版权信息
(2)文件名称,标示符(.h/.cpp),摘要
(3)当前版本号,作者/修改者,完成日期
(4)版本历史信息
/*

* Copyright (c) 2001,上海贝尔有限公司网络应用事业部

* All rights reserved.

*

* 文件名称:filename.h

* 文件标识:见配置管理计划书

* 摘要:简要描述本文件的内容

*

* 当前版本1.1

* 作者:输入作者或修改者名字

* 完成日期:2001年7月20日

*

* 取代版本:1.0

* 原作者:输入原作者或修改者名字

* 完成日期:2001年5月10日

*/
1.2 头文件的结构
头文件应有三部分内容
(1)头文件开头处的版本声明,详情见上面
(2)预处理部分
(3)函数和类结构声明
结构如下:
第一预处理 ifnedf/define/endif
第二 #include<>各种标准库里的东东
第三 #include""各种自己写的东东
备注:头文件里只放声明不放定义,即便类的成员函数体比较下也建议这么做
不要使用全局变量。
1.3 源文件.c/.cpp结构
文件结构如下
(1)定义文件开头出的版权和版本声明,如果是个人程序注明该文件内容即可

(2)对头文件引用
(3)程序的数据和代码,先全局函数,后类成员函数
1.4 目录结构
当程序的头文件数目比较多时,通常将头文件与源文件保存于不同目录便于维护,这就需要合理的目录结构,一目了然,不然时间久了完全找不到哪个是哪个。vs新建的工程就给建好了目录,Header里是头文件,Resource里是资源文件,Source里是源文件,可以参考。
二程序结构

2.1 空一行

形成统一的空行方式,记住并执行,长此以往程序的美感大大增加!

规则:

(1) 每个类声明之后,每个函数定义之后加空行

(2) 每个函数体内,逻辑上密切相关的语句之间不空行,其他地方空一行

2.2 代码行

规则

(1) 一行代码只做一件事,即只有一个;

(2) if,for,while,do等语句自己占一行,后面不要跟执行语句,无论执行语句的多寡都加上{},可有效防止写错

(3) 尽可能在定义变量的同时就初始化,以免程序大了之后前面定义后面看到就完全忘记有没有初始化了

2.3 代码行内的空格

(1)关键字如const,virtual,inline,case等关键字后留一个空格,if,for,while需要括号的关键字空格之后再跟(,如if
(a==0)

(2)函数名之后不要留空格,应紧跟左括号,如void fun()

(3)‘(’向后紧跟,),逗号和分号跟紧前面,不留空格

(4)逗号之后留一个空格,如fun(intx, int y ,int z),分号不做一行结束符时,后面留空格,主要用于for,比如for(int i=0;
i<10; i++)

(5)“=”,“+=”,“>=”,“<=”,“&&”等二元操作符前后应加空格,如(a
&& b),而一元操作符比如“++”,“!”,“&”的不加空格,比如a&b

(6)数组“[]”,引用符”.”和“->”,前后不要加空格

建议

(1) 如果表达式太长去掉一些空格就去掉一些吧%>_<%

2.4 怎么对齐是个很大的问题

规则

(1) 花括号永远独占一行,并与使用括号的程序语句对齐

(2) 代码一行写太长了要拆分,那么在低优先级操作符拆分,操作符在新行之首

(3) 最好将*,&靠近变量名,不过不一定,这种容易出错的我看还是自己惯用哪种用哪种,int &x,int *x

2.5 注释

简单直接,不要有太多解释,另外最重要的不要放在代码下面,放在代码上面或是右面

2.6 怎样安排一个类

看的那本数据结构书安排方式就很合理了,也写惯了,个人程序坚持那样完全可以,工作上的遵循公司标准就好

三命名规则

公司有自己的coding standard,此次仅为个人程序写参考

规则

(1) WIndows系统应用程序大小写混排如AddChild,其中类大写字母开头,变量小写字母开头,常量全大写,静态变量前加s_,全局变量前加g_,类的数据成员前加m_;Unix系统小写加下划线add_child

(2) 不要仅靠大小写区分如同时有变量,x和X

(3) 变量名字最好用形容词加名字,全局函数最好用动词加名词,类成员函数最好用动词

(4) 互斥的最好用反义词

(5) 最好别用value1,value2这种,这多半是为了好好偷懒

四表达式和基本语句

4.1 运算符和表达式的问题

规则

(1) 别管什么优先级,都加上括号

(2) 别写太复杂的表达式,考试题什么的完全是闲的才把程序写成那样,非要写一定加括号

4.2 if语句

规则

(1) 不要将布尔变量与TRUE,FALSE,0,1直接比较

与零值比较就写成if(flag)//flag为真,if(flag)//flag为假

(2) 如果是整型变量则千万别学上面,应该写成==,!=的方式

(3) 浮点变量= =,非要这么比的话设点一个误差常量,跟误差比比如if(x>=errorfloat)

(4) 指针用==NULL和!=NULL,别用其他的

4.3 写效率更高的循环语句

规则

(1) 长循环放于内层,短的放于外层,可减少CPU来回切换

(2) 逻辑判断最好放在循环外面

(3) for的循环控制写成半开半闭,比如0<=x<N,则总共N次,不容易算来算去的搞错

五常量其实很重要

5.1 const与#define更喜欢哪种呢

C++已经完全抛弃了#define,#define只进行替换,如果写的是个宏函数,语句稍微不对可能就会导致结果的错误,而且还找不出哪儿错了,相比下 const会进行类型安全检查,编译下就能知道有没有写错,而且有的工具也能调试const

5.2 常量布局规则

需要对外的放在头文件里,不需要的放在源文件头部,或者把所有常量放在一个头文件里

由于const必须在定义的时候初始化,而类的成员变量不能这么做,要使用const成员变量只能在构造函数的初始化列表里初始化,或者干脆不要用,用枚举就好了

六函数总是写着写着就放肆了

6.1 参数的规则

规则

(1) 无论是函数声明还是定义,里面的参数类型,参数名字写全,没有写void

(2) 两个参数要互动的时候,最好起个有意义的参数名让你知道哪个是哪个,后面跟注释而不用每次用的时候都得进去看一眼函数体咋写的

(3) 不改变值得时候记得用const

(4) 参数数目不确定的高大上函数能不写就不写

6.2 返回值的规则

没什么说的,类型写全,能const就const就好了

6.3 函数体规则

函数体内规则非常多啊

(1) 入口检查进来的参数对不对,出口检查return写好了没有

(2) 学会用断言

七重中之重,内存管理

7.1 常见的内存错误

常见的内存错误中许多也许在写一些不太占内存的简单程序时确实很少碰到,但是加进去整个程序就高大上起来了呢

(1) 内存分配未成功,结果也没检测以为成功了就用了,所以用指针p new出一段内存后用之前检查下p是不是null

(2) 内存分配成功了,但是当时没使用,后面再用的时候也忘记他有没有使用过了,所以不用也最好设个0

(3) 没释放内存,动态内存释放与申请应当配对

(4) 释放了还用,delete后应将指针设为null

7.2 指针与数组

虽然数组名字就是数组所在地址,但是数组要么在静态存储区要么在栈上,而指针可以随时乱指,指针即便指向了一个数组也不能用数组名[索引]的方式,指针名【索引】的方式找数组项,指针指向一个数组并不意味着该数组内容被复制了,如果指针瞎改,原内容将丢失,要复制必须new内存,再strcpy。

系统不可能知道指针所指内容的长度,sizeof都不行,数组当参数传递就退化成指针了

7.3 当指针做参数

如果参数做了指针,需要特别小心谨慎,记住永远不要用参数里的指针进行内存分配

7.3 malloc/free与new/delete

malloc/free是c/c++标准库,不能重载,new/delete是运算符,可以重载,而且可以使用类的析构函数,所以如果用到类一定要用new/delete

八 C++的函数总是辣么高级

8.1 函数重载

要点

(1) 函数可以依靠参数不同区分不同函数,编译器根据参数为每个重载函数产生不同的内部标示符,返回值不同却不行,因为有时候即便调用了有返回值的函数也可能根本不接收返回值

(2) C++要调用C函数需要下特别处理,用的时候找百度就好啦

extern “C”

{

C 函数调用

}

(3) 类成员函数要调用全局函数时,加::

(4) 如果参数可能发生隐式转换,函数重载就当机了,比如fun(int x),fun(double x)不能构成重载

8.2 成员函数的重载,覆盖和隐藏

重载的特征

(1) 作用域相同

(2) 函数名相同

(3) 参数不同

(4) virtual可有可无

重载前面已讲过,覆盖是指派生类函数覆盖了基类函数,特征是

(1)范围不同,分别位于子类和父类

(2)函数名相同

(3)参数相同

(4)基类该函数必须有virtual

警告警告,不要忽略C++自带的隐藏规则,隐藏但又不是覆盖,果然自作主张什么的最讨厌了

什么时候会发生隐藏

(1) 派生类函数与基类函数同名,参数不同,此时无论有无virtual基类函数被隐藏

(2) 派生类函数与基类函数同名,参数相同,基类无virtual,此时基类函数被隐藏

隐藏会引发的问题主要发生在父类定义的函数子类没定义,而又想让子类调用父类的函数,因此有同名函数时最好处理一下!!

8.3 参数的缺省值

缺省值就是默认参数的函数,只能出现在函数声明中,不能出现在定义中,而且参数只能从后向前默认,使用不熟练的话谨慎使用

8.4 运算符重载

运算符重载函数可以看做参数分别在函数名左边和右边的特殊形式函数,要点是。。。用多了才能得心应手,没办法的事

8.5 内联函数

内联函数类似宏,但是可以进行正确检查,还可以调用类的私有成员,C++中应该将宏用内联取代

要点

(1) 内联函数的关键字inline必须放在定义前,放在声明前没有用

(2) 内联不内联是编译器看情况的,要是你代码大的过分编译器可以不理会inline

九类的构造析构与赋值函数

如果类比较简单以至于都懒得写那么多函数,系统只有为你默认偷偷写上,分别是

A(void)

A(const A&a) //复制构造函数

~A(void)

A & operator=(const A &a) //赋值构造函数

9.1 要点

(1)如果类有父类,必须在初始化列表里调用父类构造函数,格式为

B::B(int x, int y):A(x){}

(3) 如果类有指针成员,一定要重视复制构造函数和赋值构造函数

(4) 如果实在懒得写复制构造函数和赋值函数又怕出错,就把他们定义为私有空函数体,这样一被调用就会出错

(5) 子类与父类析构函数应为虚函数

(6) 写复制或赋值函数需要子类不能直接操作父类私有成员,必须用父类名::父类函数的方式

十类的继承与组合

10.1 继承

只有B拥有A的所有功能和属性,才能使B继承A,避免B只有A的一部分就继承

十一一些编程经验

11.1 const多用

能用const就用const,包括const参数,const返回值,const成员函数。const成员函数使用方法为函数声明后加const

11.2 提高程序效率

(1)先优化数据结构和算法,再优化执行代码

(2)不要追求紧凑的代码,这对机器码是否高效毫无提升

(3)尽量避免代码存在饮食转换

(4)注意错误处理程序本身就有错误

(5)当心文件的I/O

(6)没事别炫技,炫的过几年绝对自己都要费好大劲来看

(7)代码能复用就复用,轻松又愉快

(8)如果库函数已经能实现的功能自己就别编了,多累啊,除非是为了学习

(9)用到跟具体系统环境有关的变量而程序又想移植就需要特别注意

(10)尝试PC-Lint,LogiScope工具进行代码审查,当然是对比较大的程序,自己的小练习就不用费事了

(11)设计的数据结构太灵活不一定是好事,越灵活越需要谨慎
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: