您好,欢迎访问三七文档
当前位置:首页 > 建筑/环境 > 工程监理 > 中国科大学继续教育学院
Object-OrientedProgramminginC++第八章C++工具中国科大学继续教育学院李艺leeyi@ustc.edu.cnC++8-1第一章C++的初步知识第二章类和对象第三章再论类和对象第四章运算符重载第五章继承与派生第六章多态性与虚函数第七章输入输出流第八章C++工具第九章模板C++8-28.1异常处理8.2命名空间8.3使用早期的函数库C++8-38.1异常处理概述:程序的错误有两种:一种是编译错误,即语法错误。另一种是在运行时发生的异常(exception)。异常处理机制只处理运行时的差错和其它例外情况,不包括编译错误。处理异常的方法有:非结构化异常处理:用exit(n)或return(n)的运行期错误处理机制,具有“一个入口,多个出口”的特点。exit()会清空流和关闭打开的文件。abort()却不会清空流,也不关闭打开的文件。结构化的异常处理:按“警告—忽略”、“对话—补救”或安全退出等模式,使程序可以在对运行条件做出适当安排或改善后继续运行下去。C++8-48.1异常处理基本思想:C++的异常处理的基本思想是将异常的检测与处理分离。在一个函数体中检测到异常条件满足,但无法确定相应的处理方法时,就引发一个异常,然后由函数的直接或间接调用者处理此异常。C++的异常处理建立在三个关键字基础之上:try、catch和throw。C++8-58.1异常处理C++异常处理语句的一般形式try{//try块内监视异常if(条件)throwexception;//由throw抛出异常…;//其它语句}catch(类型1参数1){//catch块内处理代码}catch(类型2参数2){…;}……catch(类型n参数n){…;}注意:C++通过try夺取运行期的环境控制权,即异常的引发是由程序员控制的,而不是由程序运行环境或计算机硬件控制的。任何要检测异常的语句或函数调用都必须在try语句块中执行。异常由紧跟在try块后的catch语句来捕获并处理。C++8-68.1异常处理#includeiostream.h#includemath.hfloatDiv(floatx,floaty);voidmain(){try{floata=1.0,b;while(a0.0){cout请输入被除数:;cina;cout请输入除数:;cinb;couta/b=Div(a,b)endl;}}catch(float){coutdevidingiszero.\n\n;}coutthatisok.\n;}floatDiv(floatx,floaty){if(fabs(y)0.0001)throwy;returnx/y;}方框中的代码是没有异常处理机制的代码C++8-78.1异常处理说明如果预料某段程序代码有可能发生异常,就将它放在try子句的化括号中。如果这段代码运行时真的遇到异常情况,其中的throw表达式就会抛出这个异常。出现异常时,try语句块提示编译器到哪里查找catch块,没有紧跟try块的catch块是没有作用的。当没有发生异常的时候,几乎没有和try块相关的运行时成本。查找匹配捕获处理异常的过程只在发生异常的情况下才会进行。C++8-88.1异常处理catch子句后的复合语句是异常处理程序。它捕获由throw表达式抛出的异常。异常类型说明部分指明该子句处理的异常的类型,它与函数的形参是相似的。可以是某个类型的值,也可以是引用。如果某个catch语句的参数类型与引发异常的信息数据类型相匹配,则执行该catch语句的异常处理(捕获异常),此时,由throw语句抛出的异常信息(值)传递给catch语句中的参数。C++8-98.1异常处理try语句块必须出现在前,catch紧跟在后。catch之后的圆括号中必须含有数据类型,捕获是利用数据类型匹配实现的。在try{…}和catch(…){…}语句之间不得插入任何其它C++语句。如果程序内有多个异常处理模块,则当异常发生时,系统自动查找与该异常类型相匹配的catch模块,查找次序为catch出现的次序。需要注意的是catch处理程序的出现顺序很重要,因为在一个try块中,异常处理程序是按照它出现的顺序被检查的。C++8-108.1异常处理引发异常的throw语句必须在try语句块内,或是由try语句块中直接或间接调用的函数体执行。throw语句的一般形式为:throwexception;exception表示一个异常值,它可以是任意类型的变量、对象或常量。C++8-118.1异常处理#includeiostream.hconstdoublePI=3.1416;voidinvoke(intx){try{if(x==0)throwx+5;//抛出int型的异常if(x==1)throw'A';//抛出cahr型的异常if(x==2)throwAnapple;//抛出字符串型的异常if(x==3)throwPI;//抛出double型的异常}catch(inti){coutcatchaintegeriendl;}catch(charc){coutcatchacharcendl;}catch(charstr[10]){coutcatchastringstrendl;}catch(doubled){coutcatchadoubledendl;}}程序运行结果:catchainteger5catchacharAcatchastringAnapplecatchadouble3.1416voidmain(){invoke(0);invoke(1);invoke(2);invoke(3);}C++8-128.1异常处理异常的类型匹配规则C++规定,当一个异常对象和catch子句参数类型符合下列条件时,匹配成功:如果catch子句参数类型就是异常对象的类型或其引用如果catch子句参数类型就是异常对象的public基类如果catch子句参数类型为基类指针或引用,而异常对象为派生类指针或引用。catch子句参数类型为void*,异常对象为任何类型指针。catch子句为catch-all,即catch{…}。catch处理程序按照其在try块后面的顺序依次为检测,一旦匹配,则后面的就不再检测。C++8-138.1异常处理异常的匹配规则比函数重载的匹配规则更为严格try{throwint();}catch(unsignedint){……}抛出异常的类型是int型,然而handler却期待一个unsignedint。异常处理机制不认为二者是能够匹配的类型;结果,抛出的异常没有被捕获。C++8-148.1异常处理异常重抛(re-throw):当catch捕获异常后,可能不能完全处理异常,在完成某些操作后,可以重新抛出该异常,把异常传递给上层函数的另一个catch子句,由它进一步处理。重新抛出异常的表达式仍然为:throw;被重新抛出的异常就是原来的异常对象。如:voidf(){try{throw1;}catch(inte){//dosomething;throw;}}intmain(){try{f();}catch(inte){cout“exceptioninmainis”e;}return0;}C++8-158.1异常处理#includeiostream#includestringusingnamespacestd;voidmyFunc(){try{inta;cout正在执行myFunction函数\n;stringe=输入的数据超限;cout请输入一个小于5的自然数:;while(cina){if((a1)||(a4))throwe;else{cout输入的数据a合格\n\n;if(a==1)exit(0);elsecout“请输入一个小于5的自然数:;}}}catch(string&e){cout在myFunc()中捕到一个异常endl;throwe;}}voidmain(){try{myFunc();}catch(string&e){couteendl;}}C++8-168.1异常处理重抛异常的catch子句应该把自己做过的工作告诉下一个处理异常的catch子句,往往要对异常对象做一定修改,以表达某些信息。因此catch子句中的异常声明必须被声明为引用,这样修改才能真正做在异常对象自身中,而不是拷贝中。C++8-178.1异常处理catch_all子句通常异常发生后按栈展开(stackunwinding)退出,动态分配的非类对象资源是不会自动释放的,应该在对应的catch子句中释放。因为我们不知道可能被抛出的全部异常,所以不是为每种可能的异常写一个catch子句来释放资源,而是使用通用形式的catch子句catch_all,格式为:catch(...){代码}C++8-188.1异常处理catch_all子句示例:voidfun1(){int*res;newres[100];//定义一个资源对象try{//代码包括使用资源res和某些可能引起异常抛出的操作}}catch(...){deleteres[];//正常退出前释放资源对象res;throw;//重新抛出异常}catch_all子句可以单独使用,也可以与其它catch子句联合使用。但必须放在相关catch子句表的最后。C++8-198.1异常处理异常的限制在异常处理中,由于捕获和抛出一个异常会影响到一个函数与其它函数的相互关系。因此,C++异常机制允许在函数定义后面增加一个抛出类型说明,以限制该函数可以抛出的异常类型。异常限制的一般格式如下:返回值类型函数名(参数表)throw(异常类型列表){….}使用时应特别注意,经这样定义的函数,抛出的异常数据只能是异常类型列表中的一种。C++8-208.1异常处理如果一个函数抛出的异常没有在抛出类型列表中说明或者从所列数据类型之一派生,默认的异常处理过程就是调用名为unexpected()的函数,该函数又调用terminate()函数,后者依次再调用abort()函数终止程序运行。其中,对unexpected()和terminate()用户可以提供自己的函数定义。C++8-218.1异常处理例12.3异常限制演示(VC++6.0无此功能)#includeiostream.hvoidinvoke(inttest)throw(int,char){if(test==0)throwtest;if(test==1)throw'a';if(test==2)throw123.23;}voidf(intt){try{invoke(t);}catch(intj){coutCaughtanintegerjendl;}catch(charc){coutCaughtachar:cendl;}catch(doubled){coutCaughtadoubledendl;}}voidmain(){f(0);f(1);f(2);coutEndendl;}执行结果如下:Caughtaninteger0Caughtachar:aAbnormalprogramterminateC++8-228.1异常处理异常成组将多个有某种关联的异常放在一组。这些异常通常属于某一个方面的异常。比如文件异常组。在C++异常处理中,有两种方式把多个异常成组。它们是:异常枚举成组和异常派生类成组。C++8-238.1异常处理(异常枚举成组)#includeiostream.henumerrs{err0,err1,err2};voidf(inttest){try{if(test==0)throwerr0;if(test==1)throwerr1;if(test==2)throwe
本文标题:中国科大学继续教育学院
链接地址:https://www.777doc.com/doc-4819071 .html