C++异常处理
C++异常处理机制由三部分组成,即检查(try)、抛出(throw)、和捕捉(catch)。把需要检查的语句放在try中,throw用来当出现异常是抛出异常信息,而catch则用来捕捉异常信息。
一个简单的例子:
#include<iostream> #include<cmath> using namespace std; int main() { double triangle(double,double,double); double a,b,c; cin>>a>>b>>c; try //在try中包含要检查的函数 { while(a>0&&b>0&&c>0) { cout<<"the area is :"<<triangle(a,b,c)<<endl; cin>>a>>b>>c; } } catch(double)//用catch捕获异常信息,并做出相应处理 { cout<<"a="<<a<<",b="<<b<<",c="<<c<<",that is not a triangle!"<<endl; } cout<<"end"<<endl; } double triangle(double a,double b,double c) { double s=(a+b+c)/2; if(a+b<=c||a+c<=b||b+c<=a)throw a;//当不满足三角形两边之和大于第三边的时候,抛出异常 return sqrt(s*(s-a)*(s-b)*(s-c)); }
当用户输入的数据不满足,两边之和大于第三边的时候,抛出异常,然后进行处理。
就单纯看这个例子的话,异常处理机制的用处并不大,因为处理还不如在triangle函数中直接给出警告简洁。
但是在一个大的系统那个中,包含许多模块,每个模块又包含很多函数,函数之间又相互调用,比较复杂。如果在每一个函数中都设置处理异常的程序段,会使程序过于复杂和庞大。
因此,如果在执行一个函数过程中,出现异常,可以不在本函数中立即处理,而是抛出一个异常,传给它的上一级(即调用它的函数),它的上级可以选择处理该异常,或者再往它的上级传递,如此逐级上升,如果最高一级还是无法处理,就调用系统函数terminate,使程序终止运行。
下面看个稍微复杂的例子:
#include<iostream> using namespace std; int main() { void f1(); try { f1(); //在main函数中调用f1 } catch(double) { cout<<"ERROR_MAIN"<<endl; } cout<<"END_MAIN"<<endl; return 0; } void f1() { void f2(); try { f2(); //在f1中调用f2 } catch(char) { cout<<"ERROR_F1"<<endl; } cout<<"END_F1"<<endl; } void f2() { void f3(); try { f3(); //在f2中调用f3 } catch(int) { cout<<"ERROR_F2"<<endl; } cout<<"END_F2"<<endl; } void f3() { double a=2.0; try { throw a; } catch(float) { cout<<"ERROR_F3"<<endl; } cout<<"END_F3"<<endl; }
运行结果:
ERROR_MAIN
END_MAIN
(1)f3函数在try部分抛出异常,但是不符合f3的catch,于是依次往上级找,直到找到了main函数中的catch函数,由main中的catch进行处理。
(2)如果将f3函数改为:
void f3() { double a=2.0; try { throw a; } catch(double) { cout<<"ERROR_F3"<<endl; } cout<<"END_F3"<<endl; }输出结果为:
ERROR_F3
END_F3
END_F2
END_F1
END_MAIN
f3函数中throw的异常信息立即被f3函数中的catch子语句捕获。于是执行catch子句中的语句,再执行catch后面的语句,执行完了之后,f3函数执行结束后,流程返回f2函数中调用f3函数继续向下执行。
(3)如果将f3函数改为:
void f3() { double a=2.0; try { throw a; } catch(double) { cout<<"ERROR_F3"<<endl; throw; } cout<<"END_F3"<<endl; }
输出结果为:
ERROR_F3
ERROR_MAIN
END_MAIN
f3函数中的catch语句捕捉到抛出的异常之后,输出ERROR_F3,表示收到该异常,但它又立即用throw将a再次抛出。最后别main函数中的catch语句捕获。