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