C++作为一门极其复杂的语言,使用好它是十分困难的,C++的灵活语法和复杂特性使得C++变得无比强大,但这也导致它变得十分复杂,曾经我觉得使用越多高级特性的代码就越厉害,而现在我无法赞同,绝大多数情况下,代码的可读性和可维护性是第一位的,而C++正是因此而变成了“最难”的语言,不同人、团队的C++代码风格相差甚远,各种技巧用得飞起,在这种情况下,如果能有一个规范,使得代码尽量统一,就能在一定程度上解决C++代码难以维护的问题。
尽管Google C++代码风格是针对Google自身情况制定的,限制和禁止了很多特性(由于历史原因等),但对于我这种新手,仍十分有帮助。
头文件
- 一个头文件要自给自足,使用者没有义务知道头文件是否依赖其他的头文件并自行包含。
- 根据#include头文件的原理,头文件的确是可以用来插入文本的,学习一下。
- 防止多次包含是常识。
- 超过10行、递归、含有循环和switch的函数不应内联。
头文件的包含顺序应该是:
- 与本文件最相关的头文件
- C系统文件
- C++系统文件
- 其他库的文件
本项目的文件
这样可以避免隐藏的依赖,并且保证内部错误及时被发现。
- 在#include中插入空行分割各类头文件能增加可读性
- 头文件以绝对路径包含也能增加可读性。
- 用到的所有头文件都应包含,就算你知道a.h已经被b.h包含了,后来维护的人可不一定知道啊。
作用域
- 内联命名空间一般只用于跨版本库的兼容性。
- 命名空间的最后注释出命名空间的名字。
- 只是为了封装静态成员函数而不共享静态数据创建的类,可用命名空间替代。
- 尽可能的降低代码耦合性。
类
- 避免隐式类型转换,记得加explicit。
- 分清拷贝和移动,如果你不知道类是否需要拷贝,就不要让类可以拷贝。
- 继承分清”has-a”和”is-a”,组合 > 实现继承 > 接口继承 > 私有继承,多重继承几乎用不到。
- 避免重载运算符。
- 声明次序: public -> protected -> private;
函数
- 函数尽量短小。
- 重载函数请保证用户能分清到底调用的是哪个函数,实在不行在函数名里加上参数信息。
- 避免使用默认参数,默认参数在虚函数中无法正常工作,且会干扰函数指针。
其他C++特性
- 不用异常,但我认为这只是Google的历史问题,如果是新项目,还是可以用的。
- 请用断言来保证变量非负,使用无符号型会有bug。
- size(void *) != sizeof(int),intptr_t才表示一个指针大小的整数。
- 少用宏,毕竟C++里有内联函数和const变量。
- sizeof时想清楚想要的是变量的大小还是类型的大小。
命名规范
- 命名要有描述性。
- 文件名全小写,用 _ 或 - 分割单词。
- 类型名每个单词首字母均大写;
- 普通变量和结构体变量全小写,单词用 _ 分割。
- 类数据成员在最后接下划线,这一点我认为很好用。
- 常量开头加k然后每个单词首字母都大写。
- 函数名也是每个单词首字母都大写。
- 枚举名要么和常量一样,要么和宏一样(全大写)。
注释
- 注释要在合适的地方。
- TODO是个好习惯。
格式
- 最后有一张图,一看便知。
总结
Google C++代码风格除了命名和格式,别的建议更像是Effective C++系列,有很多坑都在这本书上提过(这可是学C++不可不读的一本特别好的书)。
关于代码风格,最重要的一点就是:
保持一致
代码是给人看的,只要别人看得懂,就是ok的,代码规范也只是一个建议。
最后放一张从网上找来的图,简洁明了地总结了大部分上述知识。