抛出一个异常

More Effective C++ 学习笔记

Posted by Echo on April 25, 2020

C++ 是一个难学易用的语言!难学一方面在于其广博,因此我选择用笔记的形式精简出一些有用的条款。

函数与异常的参数

虽然函数的参数声明与 catch 子句中声明参数看起来几乎没什么区别,但其实存在这巨大的差异。

  1. 调用函数时,程序的控制权会回到函数调用处;但抛出异常时,控制权永远不会回到抛出异常的地方
  2. 对象作为参数传递给函数时不一定需要拷贝;但异常对象在传递时总是进行拷贝构造,当通过传值方式捕获时,异常对象被拷贝了两次,一个是所有异常都必须建立的临时对象,另一个则是传值方式决定的拷贝
  3. 对象作为参数传递给函数与作为异常被抛出相比,前者类型转换比后者多,后者只有两种形式:继承类与基类,类型化指针(typed pointer)与无类型指针(untyped pointer)
  4. catch 子句进行异常匹配的顺序是他们在源代码中出现的顺序,而一个对象调用虚函数时,总选择最佳匹配的类,与源代码顺序无关

注意,

throw 总是抛出当前的异常,即不改变传递出去的异常类型,不用生成一个新拷贝。

throw obj 会拷贝构造一个新异常,且拷贝构造时使用静态类型,通常会改变异常的类型(从继承类变为基类)。

要通过引用捕获异常

用过引用捕获异常,可以避免以下问题

  1. 不会为是否删除异常对象而烦恼(传指针)
  2. 能够避开 slicing 异常对象(传值)
  3. 能够捕获标准异常类型(传指针)
  4. 减少异常对象被拷贝的次数(传值,两次)

所以,尽量要通过引用捕获异常!