调用 abort() 函数来终止发现异常的程序. abort() 函数将直接终止程序而不是首先返回到主函数(在 VC 下的入口函数 main[控制台] 或 WinMain[窗体程序])中
例子:
#include <iostream> #include <cstdlib> double hmean(double a,double b) { if(a == -b) { std::cout<<"untenable arguments to hmean()"<<std::endl; std::abort(); //发现错误,终止程序. } return 2.0*a*b/(a+b); } void main() { double x,y,z; std::cout<<"Enter two number: \n"; while(std::cin>>x>>y) { z = hmean(x,y); std::cout<<"Barmonic mean of "<<x<<" and "<<y<<" is "<<z<<std::endl; std::cout<<"Enter next set of numbers < q to quit >:"; } std::cout<<"Bye!"<<std::endl; system("pause"); }
当输入为 12 -12 时候输出结果( 编译器为 VS2005 ):
[返回目录]
[工作原理][声明原型][工作流程][异常机制与函数返回机制区别][优点][注意问题][将对象作为异常类型][异常规范][exception类][bad_alloc类]
工作原理:
声明原型:
try{
... //try block
throw typeX_argX;//抛出异常
... //try block
}
catch(type1 arg1){
... //catch block
}
catch(type2 arg2){
... //catch block
}
...
catch(typeN argN) {
... //catch block
}
catch(...) //用于捕获任何异常,所以切记要把它放最后一个.
{
... //catch block
}
工作流程:
throw-catch 块是可以嵌套分层的,并通过异常对象的数据类型来进行匹配,以找到正确的 catch-block 异常错误处理代码,过程如下:
[返回子目录]
流程图如下:
在一个异常捕获的中的 try-catch 搜索过程:
(所谓的第一个 catch-block表示的是在 try 语句块后第一个紧跟的 catch-block,第二第三 catch-block 也是根据 try 位置而定)
在多个异常捕获的嵌套中的 try-catch 搜索过程:
[返回子目录]
异常机制与函数返回机制区别:
虽然 throw-catch 机制类似于函数参数和函数返回机制,但是还是有写不同之处.其中之一是函数中的返回语句将控制权返回到调用函数的函数,但是 throw 语句将函数控制权向上返回到第一个这样的函数:包含能够捕获相应异常的 try-catch 组合.
流程图:
[返回子目录]
异常捕获的优点:
[返回子目录]
异常处理中需要注意的问题:
[返回子目录]
将对象作为异常类型:
可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常另外对象可以携带信息程序员可以根据这些信息来确定引发异常的原因.并且建议传递异常类型用基类的引用或者指针.因为基类的引用或者指针有一个重要的特性:基类引用或者指针可以执行派生类对象.也就是说当有一个异常类层次结构,并要分别处理不同的异常类型,则使用基类引用将能够捕获基类和由基类派生出的派生类异常对象,而使用派生类对象只能捕获他所属类以及这个类派生而来的类的对象.
[返回子目录]
异常规范:
说明:
指出它将可能引发那些类型的异常为此可在函数定义后面加上异常规范
声明形式:
返回类型 函数名(形参列表)throw(异常类型1异常类型2 ... )
注意:
[返回子目录]
exception 类:
位于 exception 头文件中,它可以作用于其他异常类的基类,并且有一个名为 what() 的成员函数,它返回一个字符串,该字符串的特性随派生类的实现而异.
stdexcept 异常类
头文件 stdexcept 定义了其他几个异常类.
首先该类定义了 logic_error 和 runtime_error 类
logic_error 异常系列描述了典型的逻辑错误.其派生类有:
runtime_error 异常系列描述了可能在运行期间发生但难以预见和防范的错误.其派生类有:
[返回子目录]
bad_alloc 异常类:
在处理使用 new 是可能出现的内存分配问题. C++ 提供了两种可能选择的方式.实现只能有一种方式.但也可以使用编译器开关或者其他一些方法,让编程者能够选择喜欢的方式
例子:
try-catch 使用例子:
#include <iostream> using namespace std; void main() { double x(0),y(0),z(0); cout<<"enter two number:"<<endl; while(cin>>x>>y) { try{ if(x == -y) throw "x == -y isn't allowed!"; z = 2.0*x*y/(x+y); } catch(const char* s) { cout<<s<<endl; cout<<"Enter a new pair of numbers:\n"; continue; } std::cout<<"Harmonic mean of "<<x<<" and "<<y<<" is "<<z<<endl; std::cout<<"Enter next set of numbers< q to quit >:\n"; } cout<<"Bye!\n"; system("pause"); }
输出结果:
函数的异常规范:
#include <iostream> using namespace std; double hmean(double x,double y)throw(const char*) { if(x == -y) throw "x == -y isn't allowed!"; return 2.0*x*y/(x+y); } void main() { double x(0),y(0),z(0); cout<<"enter two number:"<<endl; while(cin>>x>>y) { try{ z = hmean(x,y); } catch(const char* s) { cout<<s<<endl; cout<<"Enter a new pair of numbers:\n"; continue; } std::cout<<"Harmonic mean of "<<x<<" and "<<y<<" is "<<z<<endl; std::cout<<"Enter next set of numbers< q to quit >:\n"; } cout<<"Bye!\n"; system("pause"); }
输出结果同上个例子一样
一个函数引发多个异常:
#include <iostream> using namespace std; void hmean(double x,double y)throw(const char*,int) { if(x > y) throw "x > y isn't allowed!"; if(x<0 || y<0) throw 0; } void main() { double x(0),y(0),z(0); cout<<"enter two number:"<<endl; while(cin>>x>>y) { try{ hmean(x,y); cout<<"these numbers is ok!"<<endl; } catch(const char* s) { cout<<s<<endl; cout<<"Enter a new pair of numbers:\n"; continue; } catch(int) { cout<<"invalid number!"<<endl; cout<<"Enter a new pair of numbers(greater than zero):\n"; continue; } std::cout<<"Enter next set of numbers< q to quit >:\n"; } system("pause"); }
输出结果:
捕获异常顺序:
例1 -- 基类在子类之前
#include <iostream> using namespace std; class A { public: void show(){cout<<"this is class A"<<endl;} }; class B:public A { public: void show(){cout<<"this is class B"<<endl;} }; class C:public B { public: void show(){cout<<"this is class C"<<endl;} }; void main() { int i; A a; B b; C c; cout<<"enter a number(0 is throw class A; 1 is throw class B; 2 is throw class C):\n"; while(cin>>i) { try{ switch(i) { case 0: throw a; break; case 1: throw b; break; case 2: throw c; break; default: cout<<"the number is invalid!"<<endl; } } catch(A a) { a.show(); } catch(B a) { a.show(); } catch(C a) { a.show(); } cout<<"enter a number(0 is throw class A; 1 is throw class B; 2 is throw class C):\n"; } system("pause"); }
输出结果:
例2 -- 基类在子类之后
#include <iostream> using namespace std; class A { public: void show(){cout<<"this is class A"<<endl;} }; class B:public A { public: void show(){cout<<"this is class B"<<endl;} }; class C:public B { public: void show(){cout<<"this is class C"<<endl;} }; void main() { int i; A a; B b; C c; cout<<"enter a number(0 is throw class A; 1 is throw class B; 2 is throw class C):\n"; while(cin>>i) { try{ switch(i) { case 0: throw a; break; case 1: throw b; break; case 2: throw c; break; default: cout<<"the number is invalid!"<<endl; } } catch(C a) { a.show(); } catch(B a) { a.show(); } catch(A a) { a.show(); } cout<<"enter a number(0 is throw class A; 1 is throw class B; 2 is throw class C):\n"; } system("pause"); }
输出结果:
嵌套异常捕获:
#include <iostream> using namespace std; void main() { int i; cout<<"enter a number(0 is throw_int; 1 is throw_double; 2 is throw_char):\n"; while(cin>>i) { try{ try{ switch(i) { case 0: throw 0; break; case 1: throw 1.1; break; case 2: throw 'a'; break; default: cout<<"the number is invalid!"<<endl; } } catch(char) { cout<<"in the in_catch(char)!"<<endl; } catch(double) { cout<<"in the catch(double)!"<<endl; } } catch(int) { cout<<"in the catch(int)!"<<endl; } catch(char) { cout<<"in the out_catch(char)!"<<endl; } cout<<"enter a number(0 is throw_int; 1 is throw_double; 2 is throw_char):\n"; } system("pause"); }
输出结果:
[返回目录]