- 语法错误:变量命名,分号…
- 逻辑错误:内存溢出,下标越界
- 运行错误:定义如下
- 传统异常处理的方式:使用很多的if分支语句进行处理
执行任务1
if 任务1未能被正确执行
执行错误处理程序
执行任务2
if 任务2未能正确执行
执行错误处理程序
执行任务3
- 新的异常处理方式是:检测异常,抛出异常,最后捕获异常并进行处理
try{
…… //try程序块
if err1 throw xx1
……
if err2 throw xx2
……
if errn throw xxn
}
catch(type1 arg){……} //异常类型1错误处理
catch(type2 arg){……} //异常类型2错误处理
catch(typem arg){……} //异常类型m错误处理
try-throw-catch异常处理方式
- 执行到try语句中,就进行try语块中的程序语句,这些语句是可能出现异常的语句
- 没有异常就会全部执行完毕,并且忽略掉紧挨着这个try语块的catch语句(也就是没有捕获到异常)
- 如果出现异常就会执行出现异常部分的throw,将异常抛出,try语块中的其他语句将不再执行,然后就会throw出的异常和后面的catch中的异常类型进行匹配
- 如果匹配到了,就会执行相对应catch中的语句
- 没有匹配到,就会执行系统的异常处理机制:一般是程序终止运行
异常处理的作用将底层发生的异常问题,逐级上报给更高级,一直到这个异常能被处理掉
抛出异常 捕获异常改善程序的可读性和可维护性,将异常处理代码与主程序代码分离,适合团队开发大型项目。
有力的异常检测和可能的异常恢复,以统一方式处理异常。
在异常引起系统错误之前处理异常。
处理由库函数引起的异常。
在出现无法处理的异常时执行清理工作,并以适当的方式退出程序。
在动态调用链中有序地传播异常处理。
catch根据自己要捕获的异常的类型来进行捕获异常,一旦匹配就会捕捉异常
注意:
catch在进行异常匹配的时候不会进行数据类型的默认转换,只有完全一致的数据类型才会被捕获
异常与函数异常处理可以放在一个局部函数里,每次调用这个函数的时候,就会执行这个函数里面的异常处理机制
每次调用该函数的时候就会对异常进行重置
#includeusing namespace std; void temperature(int t) { try{ if(t==100) throw "沸点!"; else if(t==0) throw "冰点!"; else cout<<"the temperature is OK..."< cout<<"temperatore="< cout< temperature(0); //L1 temperature(10); //L2 temperature(100); //L3 }
我们也可以将异常的检测和抛出的代码放在一个函数里面,然后把异常捕获的代码放在另外一个函数中,这样的异常处理会更加灵活实用
#includeusing namespace std; void temperature(int t) { if(t==100) throw "沸点!"; else if(t==0) throw "冰点!"; else cout<<"the temperature is ..."< try{ temperature(10); temperature(50); temperature(100); } catch(char *s){cout< 异常处理的几种特殊情况 1.单个catch可以捕获各种异常形式:
catch(…) { …… //异常处理代码 }catch(想捕获的异常的数据类型列表)
列表中的异常都会被这个catch所捕获
2.再次抛出异常当一个catch块无法处理该异常的时候,可以将该异常抛出,给别的catch块处理,比如说向外层传递,从底层向上一层传递
为了达成这个操作,只需要在这个catch块的结尾,加上不跑出任何异常的throw语句就ok
#includeusing namespace std; void Errhandler(int n)throw() { try{ if(n==1) throw n; cout<<"all is ok..."< cout<<"catch an int exception inside..."< try{Errhandler(1); } catch(int x){ cout<<"catch an int exception in main..."< 异常的嵌套调用 try块可以嵌套,即一个try块中可以包括另一个try块,这种嵌套可能形成一个异常处理的调用链.
#includeusing namespace std; void fc(){ try{throw "help...";} catch(int x){cout<<"in fc..int hanlder"< cout<<"no error handle..."< cout<<"in fc..char* hanlder"< int *q=new int[10]; try{ fc(); cout<<"return form fc()"< delete []q; throw; } } void fa() { char *p=new char[10]; try{ fb(); cout<<"return from fb()"< delete []p; throw; } } int main(){ try{ fa(); cout<<"return from fa"< cout<<"in main"< 异常和类 由于构造函数没有返回值,那么如果构造函数出错了该咋整?
传统方法是:
1.返回一个处于错误状态的对象,外部程序可以检查该对象状态,以便判定该对象是否被成功构造。
2.设置一个全局变量保存对象构造的状态,外部程序可以通过该变量值判断对象构造的情况。
3.在构造函数中不做对象的初始化工作,而是专门设计一个成员函数负责对象的初始化。
而异常处理机制是,在构造出错的时候就抛出异常,外部函数可以在外部捕获异常进行处理
异常类异常可以是任何类型,包括自定义类,用来传递异常信息的类就是异常类
异常类可以很简单,甚至没有数据成员
他也可以像普通类一样有构造函数,成员函数,数据成员,虚函数等等
甚至可以派生产生继承层次结构
#includeusing namespace std; const int MAX=3; class Full{}; //L1 堆栈满时抛出的异常类 class Empty{}; //L2 堆栈空时抛出的异常类 class Stack{ private: int s[MAX]; int top; public: void push(int a); int pop(); Stack(){top=-1;} }; void Stack::push(int a){ if(top>=MAX-1) throw Full(); s[++top]=a; } int Stack::pop(){ if(top<0) throw Empty(); return s[top--]; } void main(){ Stack s; try{ s.push(10); s.push(20); s.push(30); //s.push(40); //L5 将产生栈满异常 cout<<"stack(0)= "< cout<<"Exception: Stack Full"< cout<<"Exception: Stack Empty"< 异常对象 就是异常类构建的对象
#includeusing namespace std; const int MAX=3; class Full{ int a; public: Full(int i):a(i){} int getValue(){return a;} }; class Empty{}; class Stack{ private: int s[MAX]; int top; public: Stack(){top=-1;} void push(int a){ if(top>=MAX-1) throw Full(a); s[++top]=a; } int pop(){ if(top<0) throw Empty();//出现异常,抛出Empty对象 return s[top--]; } }; void main(){ Stack s; try{ s.push(10); s.push(20); s.push(30); s.push(40); } catch(Full e){ //捕获Empty类型的异常对象 cout<<"Exception: Stack Full..."< 派生异常类的处理 #includeusing namespace std; class BasicException{ public: char* Where(){return "BasicException...";} }; class FileSysException:public BasicException{ public: char *Where(){return "FileSysException...";} }; class FileNotFound:public FileSysException{ public: char *Where(){return "FileNotFound...";} }; class DiskNotFound:public FileSysException{ public: char *Where(){return "DiskNotFound...";} }; void main(){ try{ ..... //程序代码 throw FileSysException(); } catch(DiskNotFound p){cout< cout< cout< cout< ..... //程序代码 throw DiskNotFound(); } catch(BasicException p){cout< cout< cout< cout< 异常类继承结构也可以用多态实现,多态可以简化异常的捕获。
#includeusing namespace std; class BasicException{ public: virtual char* Where(){return "BasicException...";} }; class BasicException{ public: char* Where(){return "BasicException...";} }; class FileSysException:public BasicException{ public: char *Where(){return "FileSysException...";} }; class FileNotFound:public FileSysException{ public: char *Where(){return "FileNotFound...";} }; class DiskNotFound:public FileSysException{ public: char *Where(){return "DiskNotFound...";} }; void main(){ try{ //..... 程序代码 throw FileSysException(); } catch(BasicException &p){cout< //..... 程序代码 throw DiskNotFound(); } catch(BasicException &p){cout< 标准异常及其头文件 主要要去看文档



