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

C++优美代码风格和习惯总结

2013-01-20 11:29 369 查看
关于代码,什么才能被称为“好看”——或者说“优美”?几个程序员朋友讨论后的结论:

代码应该局部连贯而且功能单一:一个函数解决一个问题。而且应该很清晰。
局部代码应该能够解释,至少暗示整体的系统设计。
代码应该“自文档”,尽可能地避免注释。因为无论是在读还是写代码时,注释都是一项冗余工作。如果你需要添加注释才能帮别人理解,那么那段代码可能需要重写。

这里是idTech4引擎的编码标准,绝对值得一读。

以下对其内容进行总结:

使用占4个空格符的制表符

括号(大括号和小括号)的使用

1) Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.) The else statement starts on the same line as the last closing brace.

(也许争论最多的是把界定代码块的大括号放在哪里,对于它的使用有许多不同的风格。跟上面这一编码标准类似,在<<Professional C++>>中,把大括号放在起始语句的同一行上,但对函数名、类名或方法名则除外;所有的关键字后面使用一个空格,并使用小括号来明确操作的顺序。)

if ( x ) {

} else {

}

2) Pad parenthesized expressions with spaces

if ( x ) {

}

Instead of

if (x) {

}

x = ( y * 0.5f );

Instead of

x = (y * 0.5f);

单精度浮点数的符号最好不要省略,除非明显是双精度小数

float f = 0.5f;

Instead of

float f = 0.5;

成员命名

函数的名称首字母大写 ,往后的单词首字母都大写。如

void ThisFunctionDoesSomething( void );

变量的名称首字母小写 ,往后的单词首字母都大写。如

float maxDistanceFromPlane;

参数严格和const化

Doom的代码非常严格,尽管在我看来,const方面还不够严格。可能很多程序员都没注意到const的多种种作用。我的看法是“任何东西只要可以都应该设定为const”,我希望C++中所有的变量都默认是const。Doom参数几乎完全遵守“no in-out”规则,这意味着所有函数的参数都不能既是输入参数也是输出参数。这样,在当你向函数传入参数时,更容易理解他身上发生了什么。比如:



从这几个const中我就看出来:

这个函数不会修改作为参数传入的idPlane。我无需断言idPlane是否被修改就可以安全地使用它。
函数中的epsilon也不会被修改。
front, back, frontOnPlaneEdges and backOnPlaceEdges是输出变量,是值的写入目标。
参数列表后面的const是我最赞赏的地方。它表明idSurface::Split()不会去修改surface。这是我最喜欢的C++独有功能,因为我可以这样使用:
void f( const idSurface &s ) {
s.Split(....);
}


如果Split没有被定义为 Split(...) const,这段代码将无法编译。无论被谁所调用,f()都不会去修改外表,即使f()将surface传递给另一个函数,或者调用一些Surface::method()。const能够透露出很多关于函数甚至整个系统设计的信息,仅仅通过阅读这里的函数声明,我就明白了surface可以被plane动态地split()。这个函数不会修改surface,而是返回新的surface、front、back数据,可选地返回frontOnPlaneEdges和backOnPlaneEdges。

const规则,以及无input/output参数对我来说也许是最重要的原则,也是区分好的代码跟优美代码的关键,它能简化整个系统的理解、编辑和重构。

<<Professional C++>>: const对象就是值不会改变的对象。如果有一个const对象或对const对象的引用,编译器就不会允许在该对象上调用任何可以修改该对象内部的数据成员的方法。故要保证一个方法不会修改数据成员,具体的做法就是将方法的参数列表后用const关键字来标记。

const规范是方法原型的一部分,在方法定义中也必须带上const。

不能将静态方法声明为const,因为这是多余的。静态方法根本没有相应的类实例,故它们不可能修改内部值。

非const对象可以调用const方法和非const方法。但是,const对象和对const的引用只能调用const方法。



纵向空间

Doom从不浪费纵向空间。我们以t_stencilShadow::R_ChopWinding()为例:



整个算法只占了我1/4个屏幕,剩下的3/4可以用来观看其周围的相关代码块。

横向空间

这是我从Doom的代码中最大的收获,原来我是这样编写代码的:



根据Doom3的编码标准,始终使用相对于4个空格的tab,水平对齐其中所有类的定义:



类的成员变量和方法成员的缩排方式为:变量类型/方法返回类型置于第一排,而变量名称/方法名称置于第二排。

如下,指针的*也放在第一排,以增加可阅读性。

class idVec3 {
float			x;
float			y;
float			z;
float			Length( void ) const;
const float *	ToFloatPtr( void ) const;
};


参考文章:

idTech4引擎的编码标准 ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc
代码之美——Doom3源代码赏析 http://www.csdn.net/article/2013-01-17/2813778-the-beauty-of-doom3-source-code/2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: