1.异常是一种程序控制机制,与函数机制独立和互补
- 函数是一种以栈结构展开的上下函数衔接的程序控制系统。(系统栈,函数调用模型)
- 异常时另一种控制结构,它依附于栈结构,却可以同时设置多个异常类型作为捕捉条件, 从而以类型匹配在栈机制中跳跃回馈
2.异常设计目的
栈机制是一种高度节律性控制机制,面向对象编程去要求对象之间有方向、有目的的控制传动。从一开始,异常处理就是冲着改变程序控制结构,以适应面向对象程序更有效地工作这个主题,而不是仅仅为了进行错误处理。
异常设计出来之后,却发现在错误处理方面获取最大的好处
异常处理的基本思想
传统的异常处理机制:通过返回值来处理错误 在同一个函数中 【典型:C语言,系统库的一些函数】
C++异常处理:
1.C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层的调用者可以在适当的位置设计对不同类型的异常的处理。【实现了异常的处理与异常的发生的分离】
2.异常时专门针对抽象编程中的一系列错误处理的,C++中不能借助函数机制,函数是基于栈结构的,栈结构的特点是先进后出,依次访问,不能插队,但错误处理的特征是遇到错误信息就想要转到若干级之上重新尝试。
3.异常超脱于函数机制,决定了其对函数的跨越式回跳
4.异常跨越函数
异常基本语法
抛出异常的程序手段: void fun() { throw 表达式; } |
捕捉并处理异常 try { .... } catch(异常类型声明) ... catch(类型(参数)) .... |
1)如果有异常则通过throw操作创建一个异常对象并抛掷
2)将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺利执行到达try语句,然后执行try块内的保护段
3)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去
4)catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕捉并处理异常(或者继续抛掷异常)
5)如果匹配的处理器未能找到,则运行函数terminate将被自动调用,其缺省功能是调用abort终止程序
6)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔
程序案例
terminate调用的情况
#include <iostream> using namespace std; class A{}; class B{}; void f() { int a = 0; if(a == 0) throw A(); } void g() { try{ f(); } catch(B e){ cout<<"exception B\n"<<endl; } } int main(void) { g(); return 0; }
throw A将穿透函数 f,g,main。抵达系统最后一道防线----激发terminate函数。该函数调用了abort函数终止程序的运行。
最后一道防线的函数可以由程序员设置,从而规定其终止前的行为
修改系统默认行为
通过set_terminate函数修改捕捉不住异常的默认处理器,从而使得发生捕捉不住的异常时,被自定义函数处理。
void myTerminate(){...}
set_terminate(myTerminate); //其参数为 void(*)()
1.构造函数没有返回值,无法通过返回值来报告运行状态,所以只通过一种非函数机制的途径,即异常机制来解决构造函数的出错问题
2.异常机制与函数机制互不干涉,但捕捉的方式是基于类型匹配。捕捉相当于函数返回类型的匹配,而不是函数参数的匹配,所以捕捉不用考虑一个抛掷中有多种数据类型匹配问题
#include <iostream> using namespace std; class A{}; class B{}; int main(void) { try { int j=0; double d=2.333; char *p = "aaaaaaaaaaaaaaaa"; int key =0; cin>>key; switch (key) { case 1: throw j; break; case 2: throw d; break; case 3: throw p; break; case 4: throw A(); break; case 5: throw B(); break; default: break; } } catch(int) { cout<<"int exception\n"<<endl; } catch(double) { cout<<"double exception\n"<<endl; } catch(char*) { cout<<"char* exception\n"<<endl; } catch(A) { cout<<"class A exception\n"<<endl; } catch(B) { cout<<"class B exception\n"<<endl; } return 0; }
catch代码必须出现在try后,并且在try块后可以出现多个catch代码块,以捕捉各种不同类型的抛掷。异常机制是基于这样的原理:程序运行实质上是数据实体在做一些操作(还要一句话这样描述的,程序只要两块一个是代码区一个是数据区),因此发生异常现象的地方,一定是某个实体出了差错,该实体所对应的数据类型便作为抛掷和捕捉的依据。
异常捕捉严格按照类型匹配(苛刻程度与模板的类型匹配媲美)