异常仅用于处理错误

不要滥用异常。

不要盲目catch,不能处理的异常应继续向上传播

避免在不宜抛异常的地方抛出异常

构造异常的操作本身不应抛出异常,

// // 如果exp本身抛出异常,这一句实际抛出的就是exp抛出的异常,而非程序员原本想抛出的异常,confusing
throw exp;

下面特定的函数不宜抛异常:

  1. 全局变量和线程局部变量的构造函数:全局变量构造时,main函数还没有执行,无法捕获这个异常
  2. 析构函数
  3. delete操作符
  4. 移动构造函数
  5. 移动赋值操作符
  6. swap函数

4、5、6会被标准库调用,而其调用时不期望异常抛出。在这些地方抛异常将无法处理、或破坏标准库的某些性质。

异常的抛出与捕获

  • 只使用std::exception的派生类实例作为异常对象,不要使用基本类型
  • 抛异常时,抛对象本身而非指针,否则会造成回收责任不明确,简而言之new的异常对象谁负责delete?
  • 以左值引用的形式捕获异常,如果按值捕获异常的基类,会导致对象被切片。因为只有引用和指针有动态绑定,按值传递会导致类型转换(派生类向基类隐式转换),导致对象被切片。
  • try-catch语句有多个catch子句时,catch的顺序应该是先捕获派生类,后捕获基类