文章目录
-
- 1. 头文件
- 2. 作用域和生命周期
- 3. 类
- 4. 函数
- 5. 智能指针 [潜在BUG]
- 6. 右值引用 [可读性]
- 7. 友元:
- 8. 异常:
- 9. RTTI:
- 10. 类型转换 [可读性]
- 11. 流 [可读性]
- 12. 前置自增和自减 [程序性能]
- 13. const与constexpr [可读性]
- 14. 整型 [潜在BUG]
- 15. 64位下的可移植性 [潜在BUG]
- 16. 预处理宏 [潜在BUG]
- 17. 0字符 [可读性]
- 18. sizeof:
- 19. auto:只用于局部变量 [可读性]
- 20. 列表初始化:可用 [可读性]
- 21: lambda表达式:可用,但要显示捕获,
- 22: 模板编程:慎用,难以DEBUG [潜在BUG]
- 23: Boost库: 只使用被认可的库,如 [程序设计]
- 24: 代码书写样式
1. 头文件
- 除了?单元测试?和只含有main函数的.cpp文件,其他.cpp都要包含.h文件
- #ifndef …; #define
H; #endif 目的是避免多重
包含 [代码组织] - include [可读性, 代码维护]
#include <PATH_AFTER_SRC>/FILE.h
顺序:FILE.h, C系统文件, C++系统文件, 其他库的.h文件, 本项目内.h文件
目的:方便排查程序BUG - 直接包含原则,只考虑当前.cpp文件直接需要的.h文件 [代码组织]
- .cpp中函数和类的定义均使用.h,避免使用前置声明.因为前置声明隐藏了依赖
关系 [代码组织] - self-contained [代码组织]
2. 作用域和生命周期
2.1 命名空间
- 匿名命名空间 namespace {} //namespace [解耦]
- 作用域为当前文件
- 用于不同编译单元的解耦
- 推荐将只在当前编译单元使用的全局变量和全局函数放在该空间内
- 只用于.cpp文件
- 具名命名空间 namespace NS { //不缩进} //namespace NS [代码组织]
- 避免名字冲突
- 可用于.h文件或.cpp文件
- 禁止使用using namespace FOO;污染命名空间
- 在.cc文件,.h文件的函数,方法和类中,可使用using和别名namespace fb
= ::foo::bar::baz; [可读性]
2.2 全局/局部/静态 函数/变量
- 全局函数和静态成员函数的作用域全局可见,若只在当前.cc文件使用,推荐使
用匿名命名空间,避免在不同编译单元引起不必要的耦合 [解耦] - 具有静态生命周期的变量(全局变量,静态全局/局部/成员变量)只能使用内建类
型,如int,float,char或对应的数组,指针,不能使用类类型.原因有2个: 1)
全局变量全局可见,不同编译单元之间全局变量的初始化和析构顺序是未定义的,
违反变量使用前必须初始化的原则 2)静态变量生命周期到程序结束,多线程场景
不同线程之间同一静态对象的构造和析构顺序不确定 [潜在BUG] - 局部变量就近声明并定义 [可读性]
3. 类
3.1 构造函数
- 不在构造函数中调用自身的虚函数 [潜在BUG]
原因: 虚函数在运行时动态绑定,构造未完成时无法确定调用哪个对象(基类or子类) - 不在无法报出错误时进行可能失败的初始化 [潜在BUG]
原因: 不使用异常,无法在构造函数中报错,可使用工厂函数
3.2 隐式类型转换
- 尽可能使用explicit关键字显示表明类型转换,如类型转换运算符and单参数构造
函数 [可读性]
3.3 可拷贝类型和可移动类型
- 最低限度使用拷贝和移动,如非明显需要,禁用拷贝和移动 [执行效率]
原因: 拷贝操作(拷贝构造and拷贝赋值)常隐式调用,造成对象的不必要拷贝 - 禁用基类的拷贝和移动,否则会导致子类对象的切割 [可读性]
- 需要拷贝时显示定义拷贝构造/拷贝赋值成员函数,移动操作同理 [可读性]
3.4 结构体and类
- 只有数据成员时使用struct,否则使用class [可读性]
3.5 继承
- 只有 “is-a” 关系使用继承, “has-a” 关系使用组合 [设计逻辑]
- 必须为公有继承,原因: 不改变继承链的可见性 [设计逻辑]
- 若类含有虚函数,则析构函数也要为虚函数 [潜在BUG]
- 不过度使用protected关键字 [设计逻辑]
- 数据成员必须private [设计逻辑]
- 极少情况使用多重继承,若必须使用,则要求最多只有一个基类是非抽象类,其
他基类为以Inter