C++中的异常处理机制
C++中的捕获异常机制catch参数中实参的类型不同,采取的处理方式则不相同,且与普通的函数调用还不一样,具体表现为当抛出异常throw A()或throw obj时,对象会进行一次额外的对象复制操作。
测试类实现如下:
#include <iostream> /** * 测试异常抛出与虚函数 */ using namespace std; class A { public: A() {cout << "A() " << endl;} ~A(){cout << "~A()" << endl;} A(const A& a){cout << "A(a)" << endl;} virtual void func(){cout << "A::func()" << endl;} }; class B:public A { B() {cout << "B()" << endl;} B(const B &b) {cout << "B(b)" << endl;} ~B(){cout << "~B()" << endl;} virtual void func() {cout << "B::func()" << endl;} };
1) 当采用对象传递方式捕获异常时,在对象中会发生两次复制操作,一次为对象a复制给临时对象,二次为临时对象通过引用方式传递给实参b。
void f1(const A &a) { try { cout << "------ function f1: --------" << endl; throw a; } catch( A b) { cout << "exception A b" << endl; } cout << "---- function f1 -------" << endl; }
该段代码执行结果如下:
------ function f1: --------
A(a)
A(a)
exception A b
~A()
~A()
---- function f1 -------
2) 当采用引用方式捕获异常时,就会少了上面第二次的复制开销,即生成临时对象直接作为参数传递。
void f2(const A &a) { try { cout << "------ function f2: --------" << endl; throw a; } catch( const A &b) { cout << "exception A &b" << endl; } cout << "---- function f2 -------" << endl; }
执行结果如下:
------ function f2: -------- A(a) exception A &b ~A() ---- function f2 -------
3) 如果直接抛出引用对象,系统会报错,因为异常处理机制不局限于当前函数,有可能在该函数之外。
void f3(const A &a) { try { cout << "------ function f3: --------" << endl; throw &a;//引用异常,系统会意外终止 } catch(const A &b) { cout << "exception A &b" << endl; } cout << "---- function f3 -------" << endl; }
4) 抛出异常时,可直接抛出对象,也可生成一个对象,不同的是这样会显式调用构造函数非复制构造函数。
void f4(const A &a) { try { cout << "------ function f4: --------" << endl; throw A(); } catch(const A &b) { cout << "exception A &b" << endl; } cout << "---- function f4 -------" << endl; }
执行结果如下:
------ function f4: -------- A() exception A &b ~A() ---- function f4 -------
5) 在处理带有继承的异常类时,异常处理规则不是按照虚函数继承中”最优匹配(best fit)”原则,而是”最先匹配(first fit)”原则进行处理。
void f5(const B& b) { try { cout << "------ function f5: --------" << endl; throw b; } catch(const A &a) { cout << "exception A &a" << endl; } catch(const B &b1) { cout << "exception B &b1" << endl; } cout << "---- function f5 -------" << endl; }
该异常会匹配A而非B:
------ function f5: -------- A() B(b) exception A &a ~B() ~A() ---- function f5 -------