1 / 15

第十章 异常处理

第十章 异常处理. 类的设计者很难考虑各种错误 类的使用者无法检查何时出现错误. 对象类型决定了所抛出的是哪种异常. 10.1 用异常来处理错误 错误检查(类:抛出异常) C++ 异常处理机制 错误处理(使用者:具体处理) 抛出异常: throw 异常对象; 处理异常: try { // 检测抛出异常对象范围 } catch ( 异常对象类型) {

Download Presentation

第十章 异常处理

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十章 异常处理 类的设计者很难考虑各种错误 类的使用者无法检查何时出现错误

  2. 对象类型决定了所抛出的是哪种异常 10.1 用异常来处理错误 错误检查(类:抛出异常) C++异常处理机制 错误处理(使用者:具体处理) 抛出异常: throw异常对象; 处理异常: try { //检测抛出异常对象范围 } catch(异常对象类型) { //异常处理 } 越界错误: class Vector{ int *p; int sz; public: Vector(int s) { p=new int [s]; sz=s; } ~Vector( ) { delete [ ] p ; } int size( ) { return sz; } int& operator[ ] (int i); class Range { }; }; throw只有在try块内抛出才有效 异常类

  3. 异常类对象 Range re; throw re; int& Vector:: operator[ ] (int i); { if(i>=0 && i<sz) return p[i]; throw Range( ); } 如何使用: #include<iostream.h> #include<stdlib.h> void f( Vector& v ) { //…… try { v[0]=1; v[v.size( )+10]=10; v[0]=0; } catch( Vector:: Range ) { cout<<“Vector: out of Range”<<endl; exit(1); } cout<<“pass”<<endl; } 发现越界,抛出异常对象 跳出try块,进行catch参数匹配 无异常 跳过catch块,往下执行

  4. throw抛出异常,但当前函数无try块或catch未捕获到throw抛出异常,但当前函数无try块或catch未捕获到 向上层调用函数继续抛出 直到最外层仍不处理所抛出的异常 自动调用void terminate( )中断程序执行 class X { }; class X { }; void f1( ) void f1( ) { { throw X( ); throw X( ); } } void f2( ) void f2( ) { { f1( ); f1( ); } } void f3( ) { void main( ) f2( ); { } f2( ); void f4( ) } { try { f3( ); } catch(X) { //…… } } terminate( )调用abort( )

  5. 指向terminate( )原来调用的函数 指向terminate( )现在要调用的函数 可用set_terminate( )改变terminate( )的缺省行为。 set_terminate( )的原型为: typedef void ( *PFV) ( ); PFV set_terminate(PFV); #include<iostream.h> #include<exception.h> typedef void ( *PFV) ( ); void error_message( ) { cout<<“error”<<endl; } void f( ) { PFV p=set_terminate(&error_message); //…… set_terminate(p); //…… }

  6. 抛出的异常对象,可利用其数据成员和成员函数记录一些异常状态。抛出的异常对象,可利用其数据成员和成员函数记录一些异常状态。 class Vector{ int *p; int sz; public: class Range { public: int index; Range(int i): index(i) { } }; Vector(int s) { p=new int [s]; sz=s; } ~Vector( ) { delete [ ] p ; } int size( ) { return sz; } int& operator[ ] (int i); }; int& Vector:: operator[ ] (int i); { if(i>=0 && i<sz) return p[i]; throw Range( i ); } void f( Vector& v ) { try { v[0]=1; v[v.size( )+10]=10; } catch( Vector:: Range r ) { cout<<“bad index”<<r.index<<endl; } } catch用捕获的异常对象初始化r

  7. 10.2 多个异常 10.2.1 处理多个异常 #include<iostream.h> #include <stdlib.h> class Vector{ int *p; int sz; enum {max=3200}; public: class Range { }; class Size { }; Vector(int s); int size( ) const { return sz; } int& operator[ ] (int i); }; Vector:: Vector(int size) { if(size<0 || max<size) throw Size( ); p=new int[size]; sz=size; } 下标越界异常 数组尺寸异常 尺寸异常发生在构造函数中

  8. try块有异常抛出 检测第一个catch 匹配 Vector的使用者处理异常: void f( ) { try { use_Vectors( ); } catch(Vector:: Range) { cout<<“Vector:: Range error”; exit(1); } catch(Vector:: Size) { cout<<“Vector:: Size error”; exit(1); } } 若use_Vectors定义为: void use_Vectors( ) { Vector ve( 32010 ); //…… } 输出结果? 若use_Vectors定义为: void use_Vectors( ) { Vector ve( 100 ); ve[105]=25; //…… } 输出结果? No yes 第一个catch块 检测第二个catch yes 匹配 No 第二个catch块 下一catch 跳过其它catch

  9. 并非所有异常处理都放在一个函数里 #include<iostream.h> #include<stdlib.h> #include”Vectro.h” void use_Vector( Vector &v, int range ) { v[range]=21; } Vector create_Vector(int size) { return Vector(size); } void f2( Vector &v, int range) { try { use_Vector(v, range); } catch(Vector:: Range) { cout<<“Vector:: Range error”<<endl; exit(1); } }

  10. void f1( int size, int range) { try { Vector ve=createVectors(size); f2(ve, range); } catch(Vector:: Size) { size=size>0? --size:0; cout<<size<<endl; f1(size, range); } } void main( ) { int size, range; cout<<“input size, range:”; cin>>size>>range; f1(size, range); }

  11. 语义相关放在一起 缺点:不能象类对象那样带有异常信息 10.2.2 用枚举组织异常 异常种类繁多 用户难以管理合理地组织 enum Matherr { Overflow, Underflow, Zerodivide /*…*/}; void f( ) { try { //…… } catch(Matherr m) { swith(m) { case Overflow: //…… case Underflow: //…… } } } 10.2.3 用派生类组织异常 class Matherr { /*…*/ }; class Overflow: public Matherr { /*…*/ }; class Underflow: public Matherr { /*…*/ }; //…… try { //…… } catch(Overflow) { /*…*/ } catch(Underflow) { /*…*/ } //…… 缺点:每种异常都要有相应处理程序 基类异常处理

  12. catch(…)可捕获任何异常 缺点:走向另一极端 try { //…… } catch(Overflow) { //处理上溢出 } catch(Matherr) { //处理除上溢出之外的算术库其它异常 } //…… catch的先后次序为:先派生,后基类,最后省略参数 10.2.4 用虚函数组织异常 在Matherr中添加一个Int_overflow异常: class Matherr { //…… void debug_print( ); }; class Int_overflow: public Matherr { public: char * cp; int opr1, opr2; Int_overflow(const char* p, int a, int b) { op=p; opr1=a; opr2=b; } void debug_print( ) { cout<<op<<‘(‘<<opr1<<‘,’<<opr2<<‘)’; } };

  13. void f( ) { try { //抛出Int_overflow异常 } catch(Matherr m) { m.debug_print( ); //…… } } 引入虚函数: class Matherr { //…… virtual void debug_print( ); }; class Int_overflow: public Matherr { public: char * cp; int opr1, opr2; Int_overflow(const char* p, int a, int b) { op=p; opr1=a; opr2=b; } virtual void debug_print( ) { cout<<op<<‘(‘<<opr1<<‘,’<<opr2<<‘)’; } }; f( )中的catch(Matherr m)改为catch(Matherr &m)

  14. f1只处理X,Y及其派生类异常 f2可处理各种异常 10.3 异常的接口说明 10.3.1 异常接口说明形式 一个函数往往处理异常的子集,为了表示函数和异常之间的关系 函数返回值类型 函数名(函数参数)throw(类型1,类型2,…) void f1( ) throw(X,Y); int f2( ); int f3( ) throw( ); 10.3.2 unexpected( )函数 异常接口有说明,但函数未处理 异常被重新抛出; 遇到异常未在接口中说明 调用unexpected( )函数 void f( ) throw(x2,x3) { //未处理x2,x3异常 } void f( ) { try { //…… } catch(x2) { throw; } f3不处理任何异常

  15. 原型为:void unexpected( ) 缺省调用terminate( )函数 catch(x3) { throw; } catch(…) { unexpected( ); } }

More Related