首页 c++基础知识10异常处理机制

c++基础知识10异常处理机制

举报
开通vip

c++基础知识10异常处理机制第十章异常处理  大型和十分复杂的程序往往会产生一些很难查找的甚至是无法避免的运行时错误。当发生运行时错误时,不能简单地结束程序运行,而是退回到任务的起点,指出错误,并由用户决定下一步工作。面向对象的异常处理(exceptionhandling)机制是C++语言用以解决这个问题的有力工具。函数执行时,放在try(测试)程序块中的任何类型的数据对象发生异常,都可被throw表达式抛出,随即逆调用链退回,直到被catch子句捕获,并在此执行异常处理,报告出现的异常等情况。从抛出到捕获,应将各嵌套调用函数残存在栈中的自动...

c++基础知识10异常处理机制
第十章异常处理  大型和十分复杂的程序往往会产生一些很难查找的甚至是无法避免的运行时错误。当发生运行时错误时,不能简单地结束程序运行,而是退回到任务的起点,指出错误,并由用户决定下一步工作。面向对象的异常处理(exceptionhandling)机制是C++语言用以解决这个问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 的有力工具。函数执行时,放在try(测试)程序块中的任何类型的数据对象发生异常,都可被throw 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 达式抛出,随即逆调用链退回,直到被catch子句捕获,并在此执行异常处理, 报告 软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载 出现的异常等情况。从抛出到捕获,应将各嵌套调用函数残存在栈中的自动对象、自动变量和现场保护内容等进行清除。如果已退到入口函数还未捕获则由terminate()函数来终结入口函数。第十章异常处理10.1异常的概念10.3栈展开与异常捕获10.2异常处理的机制10.5异常和继承10.7C++标准库异常类层次结构(选读)10.6异常规范(选读)10.4异常的重新抛出和catch_all子句10.1异常的概念  异常概念的引入:异常(exception)是程序可能检测到的,运行时不正常的情况,如存储空间耗尽、数组越界、被0除等等。可以预见可能发生在什么地方,但是无法确知怎样发生和何时发生。特别在一个大型的程序(软件)中,程序各部分是由不同的小组编写的,它们由公共接口连起来,错误可能就发生在相互的配合上,也可能发生在事先根本想不到的个别的条件组合上。C++提供了一些内置的语言特性来产生(raise)或抛出(throw)异常,用以通知“异常已经发生”,然后由预先安排的程序段来捕获(catch)异常,并对它进行处理。这种机制可以在C++程序的两个无关(往往是独立开发)的部分进行“异常”通信。由程序某一部分引发了另一部分的异常,这一异常可回到引起异常的部分去处理(逆着程序函数的调用链)。10.2异常处理的机制测到栈满或空就抛出一个异常。templatevoidStack::Push(constT&data){if(IsFull())throwpushOnFull(data);//注意加了括号,是构造一个无名对象elements[++top]=data;}templateTStack::Pop(){if(IsEmpty())throwpopOnEmpty();returnelements[top--];}注意pushOnFull是类,C++要求抛出的必须是对象,所以必须有“()”,即调用构造函数建立一个对象。异常与异常抛出:以栈为例,异常类声明如下:classpopOnEmpty{...};//栈空异常classpushOnFull{...};//栈满异常10.2异常处理的机制throw表达式抛出异常为异常处理的第一步。在堆栈的压栈和出栈操作中发生错误而抛出的异常,理所当然地应由调用堆栈的程序来处理。异常并非总是类对象,throw表达式也可以抛出任何类型的对象,如枚举、整数等等。但最常用的是类对象。在C++中异常抛出与异常处理之间有一整套程序设计的机制。首先采用关键字try,构成一个try块(tryblock),它包含了抛出异常的语句。当然也可以是包含了这样的调用语句,该语句所调用的函数中有能够抛出异常的语句。异常处理机制:10.2异常处理的机制intmain(){inta[9]={1,2,3,4,5,6,7,8,9},b[9]={0},i;stackistack(8);try{for(i=0;i<9;i++)istack.Push(a[i]);istack.PrintStack();}catch(pushOnFull){cerr<<”栈满”<){cerr<<”栈空”<classpushOnFull{T_value;public:pushOnFull(Ti):_value(i){}//或写为pushOnFull(Ti){_value=i;}Tvalue(){return_value;}};新的私有数据成员_value保存那些不能被压入栈中的值。该值即调用构造函数时的实参。catch子句异常声明探讨:异常声明中可以是一个对象声明。以栈为例。当栈满时,要求在异常对象中保存不能被压入到栈中的值,pushOnFull类可定义如下:10.3栈展开与异常捕获在catch子句中,要取得_value,须调用pushOnFull中的成员函数value():catch(pushOnFulleObj){cerr<<”栈满”<&eObj){cerr<<”栈满”< 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 是定义函数try块(FunctiontryBlock)。这种方法是把整个函数包括在try块中。一个函数try块把一组catch子句同一个函数体相关联。如果函数体中的语句抛出一个异常,则考虑跟在函数体后面的处理代码来处理该异常。函数try块对构造函数尤其有用。【例10.1_1】定义函数try块(FunctiontryBlock)。函数try块的使用:寻找匹配的catch子句有固定的过程:如果throw表达式位于try块中,则检查与try块相关联的catch子句列表,看是否有一个子句能够处理该异常,有匹配的,则该异常被处理;找不到匹配的catch子句,则在主调函数中继续查找。如果一个函数调用在退出时带有一个被抛出的异常未能处理,而且这个调用位于一个try块中,则检查与该try块相关联的catch子句列表,看是否有一个子句匹配,有,则处理该异常;没有,则查找过程在该函数的主调函数中继续进行。即这个查找过程逆着嵌套的函数调用链向上继续,直到找到处理该异常的catch子句。只要遇到第一个匹配的catch子句,就会进入该catch子句,进行处理,查找过程结束。10.3栈展开与异常捕获  在栈异常处理的例子中,对popOnEmpty,首先应在istack的成员函数Pop()中找,因为Pop()中没有try块,不存在catch子句,所以Pop()带着一个异常退出。下一步是检查调用Pop()的函数,这里是main(),在main()中对Pop()的调用位于一个try块中,则可用与该try块关联的catch子句列表中的某一个来处理,找到第一个popOnEmpty类型异常声明的catch子句,并进入该子句进行异常处理。栈展开:因发生异常而逐步退出复合语句和函数定义的过程,被称为栈展开(stackunwinding)。这是异常处理的核心技术。异常对程序的影响通常不仅是在发生异常的那个局部范围中,而且可能逆调用链而上,甚至整个任务。因此,异常处理应该在其对程序影响的终结处进行,甚至是在调用该任务的菜单处进行。10.3栈展开与异常捕获 在栈展开期间,在退出的域中有某个局部量是类对象,栈展开过程将自动调用该对象的析构函数,完成资源的释放。所以C++异常处理过程本质上反映的是“资源获取是由构造函数实现,而资源释放是由析构函数完成”。采用面向对象的程序设计,取得资源的动作封装在类的构造函数中,释放资源的动作封装在类的析构函数中,当一个函数带着未处理的异常退出时,函数中这种类对象被自动销毁,资源(包括动态空间分配的资源和打开的文件)释放。所以由文件重构对象应该放在构造函数中,把对象存入文件应该放在析构函数中。栈展开时资源的释放:异常处理应该用于面向对象的程序设计。对非面向对象的程序设计如果函数动态获得过资源,因异常,这些资源的释放语句可能被忽略,则这些资源将永远不会被自动释放。10.3栈展开与异常捕获 异常不能够保持在未被处理的状态。异常表示一个程序不能够继续正常执行,这是非常严重的问题,如果没有找到处理代码,程序就调用C++标准库中定义的函数terminate()。异常对象的探讨:异常对象是在throw表达式中建立并抛出:throw表达式通过调用异常类的构造函数创建一个临时对象,然后把这个临时对象复制到一个被称为异常对象(exceptionobject)的存贮区中,它保证会持续到异常被处理完。10.3栈展开与异常捕获函数调用和异常处理的区别:建立函数调用所需要的全部信息在编译时已经获得,而异常处理机制要求运行时的支持。对于普通函数调用,通过函数重载解析过程,编译器知道在调用点上哪个函数会真正被调用。但对于异常处理,编译器不知道特定的throw表达式的catch子句在哪个函数中,以及在处理异常之后执行权被转移到哪儿。这些都在运行时刻决定,异常是随机发生的,异常处理的catch子句是逆调用链进行查找,这与运行时的多态­——虚函数也是不一样的。当一个异常不存在处理代码时,系统无法通知用户,所以要有terminate()函数,它是一种运行机制,当没有处理代码(catch子句)能够匹配,被抛出的异常时由它通知用户。10.4异常的重新抛出和catch_all子句(选读)rethrow表达式仍为:throw;但仅有一个关键字,因为异常类型在catch语句中已经有了,不必再指明。被重新抛出的异常就是原来的异常对象。但是重新抛出异常的catch子句应该把自己做过的工作告诉下一个处理异常的catch子句,往往要对异常对象做一定修改,以表达某些信息,因此catch子句中的异常声明必须被声明为引用,这样修改才能真正做在异常对象自身中,而不是副本中。异常的重新抛出与连续处理:当catch语句捕获一个异常后,可能不能完全处理异常,完成某些操作后,该异常必须由函数链中更上级的函数来处理,这时catch子句可以重新抛出(rethrow)该异常,把异常传递给函数调用链中更上级的另一个catch子句,由它进行进一步处理。10.4异常的重新抛出和catch_all子句(选读)通用catch子句(catch_all):catch(...){代码*/}任何异常都可以进入这个catch子句。这里的三个点称为省略号。花括号中的复合语句用来执行指定操作。异常发生后按栈展开(stackunwinding)退出,动态分配的非类对象资源不会自动释放的,通常在catch_all子句中释放。voidfun1(){int*res;res=newint[100];//定义一个资源对象try{//代码包括使用资源res和某些可能引起异常抛出的操作}//异常可能有多种catch(...){//不论是那种异常都在此释放delete[]res;//释放资源对象resthrow;}//重新抛出异常delete[]res;}//正常退出前释放资源对象res;10.4异常的重新抛出和catch_all子句(选读)  catch_all子句可以单独使用,也可以与其它catch子句联合使用。如果联合使用,它必须放在相关catch子句表的最后。catch子句被检查的顺序与它们在try块之后排列顺序相同,一旦找到了一个匹配,则后续的catch子句将不再检查,按此规则,catch_all子句(catch(...){})处理表前面所列各种异常之外的异常。如果只用catch_all子句进行某项操作,则其他的操作应由catch子句重新抛出异常,逆调用链去查找新的处理子句来处理,不能在子句列表中再安排一个处理同一异常的子句,因为第二个子句是永远执行不到的。通用catch子句的应用:10.5异常和继承定义一个称为Excp的基类,由它来打印错误信息:classExcp{public:voidprint(stringmsg){cerr< 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 ,可以随着函数声明列出该函数可能抛出的异常,并保证该函数不会抛出任何其他类型的异常,在stack类定义中可有:voidPush(constT&data)throw(pushOnFull);TPop()throw(popOnEmpty);成员函数类内声明和类外定义必须必须在两处都有相同的异常规范,同样的异常规范。异常规范的引入:10.6异常规范classCBase{public:virtualintfun1(int)throw();virtualintfun2(int)throw(int);virtualstringfun3()throw(int,string);};classCDerived:publicCBase{public:intfun1(int)throw(int);//错!异常规范不如throw()严格intfun2(int)throw(int);//对!有相同的异常规范stringfun3()throw(string);}//对!异常规范比throw(int,string)更严格虚函数中的异常规范:派生类的虚拟函数的异常规范必须与基类虚函数的异常一样或更严格。因为当派生类的虚函数被指向基类类型的指针调用时,保证不会违背基类成员函数的异常规范。10.7C++标准库的异常类层次结构(选读)exception类的接口如下:namespacestd{//注意在名字空间域std中classexception{public:exception()throw();//默认构造函数exception(constexception&)throw();//复制构造函数exception&operator=(constexception&)throw();//复制赋值操作符virtual~exception()throw();//析构函数virtualconstchar*what()constthrow();//返回一个C风格的字符串,目的是为抛出的异常提供文本描述};}C++标准库中的异常层次的根类被称为exception,定义在库的头文件中10.7C++标准库的异常类层次结构(选读)C++标准库提供的逻辑异常:invalid_argument异常,接收到一个无效的实参,抛出该异常。out_of_range异常,收到一个不在预期范围中的实参,则抛出。length_error异常,报告企图产生“长度值超出最大允许值”的对象domain_error异常,用以报告域错误(domainerror)。C++标准库提供的运行时异常:range_error异常,报告内部计算中的范围错误。overflow_error异常,报告算术溢出错误。underflow_error异常,报告算术下溢错误。以上三个异常是由runtime_error类派生的。bad_alloc异常。当new()操作符不能分配所要求的存储区时,会抛出该异常。它是由基类exception派生的。【例10.3】为类模板Array重新定义下标操作符[],如果索引值越界,它会抛出一个out_of_range类型的异常。第十章异常处理完谢谢![例10.1]堆栈异常处理templateclasspushOnFull{//栈满异常声明T_value;public:pushOnFull(Ti){_value=i;}Tvalue(){return_value;}voidprint(){cerr<<"栈满,"<classpopOnEmpty{//栈空异常声明public:voidprint(){cerr<<"栈已空,无法出栈"<classStack{inttop;//栈顶指针(下标)T*elements;//动态建立的数值intmaxSize;//栈最大允纳的元素个数public:Stack(int=20);//栈如不指定大小,设为20元素~Stack(){delete[]elements;}voidPush(constT&data)throw(pushOnFull);//压栈TPop()throw(popOnEmpty);//弹出,top--TGetElem(inti){returnelements[i];}//返回指定元素voidMakeEmpty(){top=-1;}//清空栈boolIsEmpty()const{returntop==-1;}//判栈空boolIsFull()const{returntop==maxSize-1;}//判栈满voidPrintStack();//输出栈内所有数据};[例10.1]堆栈异常处理templatevoidStack::Push(constT&data){if(IsFull())throwpushOnFull(data);//栈满则抛出异常elements[++top]=data;//栈顶指针先加1,元素再进栈,top是指向栈顶元素}templateTStack::Pop(){if(IsEmpty())throwpopOnEmpty();//栈已空则不能退栈,抛出异常returnelements[top--];//返回栈顶元素,同时栈顶指针退1}[例10.1]堆栈异常处理intmain(){inta[9]={1,2,3,4,5,6,7,8,9},b[9]={0},i;Stackistack(8);try{for(i=0;i<9;i++)istack.Push(a[i]);//到a[8]时栈满,异常istack.PrintStack();}catch(pushOnFull&eObj){eObj.print();}try{for(i=0;i<9;i++)b[i]=istack.Pop();}catch(popOnEmpty&eObj){eObj.print();}for(i=0;i<9;i++)cout<istack(8);for(i=0;i<9;i++)istack.Push(a[i]);//到a[8]时栈满,异常istack.PrintStack();for(i=0;i<9;i++)b[i]=istack.Pop();for(i=0;i<9;i++)cout<&eObj){eObj.print();return1;}catch(popOnEmpty&eObj){eObj.print();return2;}[例10.2]异常层次结构中的虚函数classExcp{public:virtualvoidprint(){cerr<<"发生异常"<classArray{intsize;elemType*ia;public:explicitArray(intsz=DefaultArraySize){size=sz;ia=newelemType[size];}~Array(){delete[]ia;}elemType&operator[](intix)const{//下标运算符[]重载if(ix<0||ix>=size){//增加异常抛出,防止索引值越界stringeObj="out_of_rangeerrorinArray::operator[]()";throwout_of_range(eObj);}returnia[ix];}//保留原来[]的所有索引方式private:intsize;elemType*ia;};[例10.3]Array重新定义下标操作符[]intmain(){inti;Arrayarr;try{for(i=0;i<=DefaultArraySize;i++){arr[i]=i+1;//写入ia[10]时出界cout<::operator[]()"return-1;}return0;}
本文档为【c++基础知识10异常处理机制】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
机构认证用户
爱赢
公司经营范围:网络软件设计、制作、图文设计、影视制作(编辑)
格式:ppt
大小:276KB
软件:PowerPoint
页数:0
分类:教育学
上传时间:2021-02-19
浏览量:1