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 -------