原则12:理解“抛出一个异常”与“传递一个异常”或“调用一个虚函数”间的差异

向函数传参与异常传递是不同的,因为向函数传参,程序控制权会返回到函数调用处而异常传递回不去。
传递异常对象是要经过复制的,因为如果不这样做,原来的异常对象会因为异常而销毁,那么异常就不能继续传递出来了。如果你把这个异常对象设置成静态的,那么它不会被销毁,但是异常传递机制仍然会复制这个异常对象。从频繁的对象复制过程可以看出,异常机制是非常慢的。
这里有一个现象,如果你用父类引用去指向一个子类对象,并把这个引用作为异常对象抛出,那么异常对象是父类类型,即静态绑定,而非动态绑定。
如下这两种异常写法是不同的。

原则12:理解“抛出一个异常”与“传递一个异常”或“调用一个虚函数”间的差异_第1张图片

Throw后面为空的,起到的是传递异常的作用,而throw后面是w的则是在catch块上面的try块中发生的新的异常。所以可以看出前面的不涉及到对象的复制它快,后面的需要复制对象它慢。
函数传参与异常传递的第二个区别。函数传参必须让临时对象传递到const形参里面才行,而异常抛出的对象则可以通过引用捕获无需const。
不要把throw指向对象的指针。因为异常传递的过程中会复制这个指针,而指针所指之物已经不复存在了,所以这个指针就是空吊,会发生未定义行为,这是危险的。
如果你以对象值传递的方式抛出异常,那么与值传递的方式给函数传参会多出一个临时对象来,那就是所有异常都必须创建的临时对象。而二者相同的都是传参时复制的对象,所以异常比函数多了一个临时对象。
异常传递与函数传参的下一个区别。函数传参会进行隐式类型转换,而catch是精确匹配。虽然如此,但是catch允许基类对象捕获子类异常,另外,catch还允许void 指针捕获非void指针异常,虽然这个我没见过。
Catch捕获异常是按照顺序来匹配的,即第一个能捕获异常的catch,如果还有其他能捕获该异常的catch一律跳过,C++中的动态绑定是根据最合适的类型进行匹配的,这个与catch是不同的。
还有,catch中的异常类的出现顺序是,子类型catch在父类型catch上面,不然会有警告,这个我倒是没遇到过,不过它倒是我的习惯写法。

多谢捧场

如果您觉得我的文章有价值,那么赏脸打赏一个,鄙人感激不尽。不过,不打赏看看也是好的,如果有不对的地方,还请您多多指正。


原则12:理解“抛出一个异常”与“传递一个异常”或“调用一个虚函数”间的差异_第2张图片

你可能感兴趣的:(原则12:理解“抛出一个异常”与“传递一个异常”或“调用一个虚函数”间的差异)