条款 十二: 了解[掷出一个exception]与[传递一个参数]或[调用一个虚函数]之间的差异
该条款中指出,函数参数的声明语法与catch子句的声明语法,简直如出一辙。虽然[从掷出端传递一个exception到catch子句]与[从函数调用端传递一个自变量到函数参数]基本上是一样的,但是其区别如下:
区别1:虽然函数参数和exception的传递方式有三种:by value,by reference, by pointer。然而是传递参数还是exception,对于调用端来说完全不同。调用一个函数,控制权最终会回到调用端,但是掷出一个exception,控制权将不会再回到掷出端
区别2:函数调用中将一个临时对象传递给一个non-const reference参数是不允许的,但对exceptions则属合法
区别3:[掷出exception]和[传递函数参数]相比,前者会多构造一个[被掷出物]的副本(并与稍后解析)
该书中指出,“不论被捕捉的exception是以by value或by reference方式传递(不可能以by pointer方式传递),都会发生exception object对象的复制行为,而交到catch子句的正是那个副本。但掷出的exception object对象被copy时,将调用对象的copy constructor执行,且该copy constructor相应于该对象的静态型别而非动态型别。”
[exception objects是其对象的副本],对如何在catch区块内传播exception,带来冲击:
这两个catch区块间的差异就是:前者重新掷出当前的exception,后者掷出的是当前exception的副本
[自变量传递]与[exception传播]两动作区别:
其一、对象从[调用端或掷出段]被搬移到[参数或catch子句]时的做法有所不同
其二、[调用端或掷出段]和[被调用者或捕获者]之间型别吻合规则不同。
其三、catch子句总是依出现次序做匹配尝试,最先匹配的将处理该异常
[exception与catch子句相匹配]的过程中,仅有两种转换可以发生:
——继承架构中的类转换(inheritance-based conversions),参考exception继承体系,针对base class exception而写的catch子
句,可以处理型别为derived class的exception。该规则适用与by value,by reference以及by pointer三种形式的catch
——但从一个[有型指针]转为[无型指针]时。例如:针对const void* 指针而设计的catch子句,可捕获任何指针型别的exception