




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第10章异常处理
程序设计不仅应考虑程序的正确性,还要考虑程序的容错能力。在程序设计期间,要充分考虑程序运行时可能出现的各种异常问题,在出现各种异常情况时,程序应有适当的处理措施,不轻易出现死机,或退出系统,或发生数据丢失等灾难性后果,提高程序的健壮性。
C++提供了异常处理的机制。本章介绍异常的概念、C++的异常处理机制和方法。学习内容:1.理解异常的概念、异常处理的思想;2.理解C++中try-throw-catch异常处理机制;3.掌握异常处理方法,学会处理程序中常见的异常。第10章异常处理第10章异常处理10.1异常的概念和异常处理的基本思想
10.2异常处理机制10.3异常处理实例补充10.1
异常的概念和异常处理的基本思想
程序的错误通常包括:1.语法错误。指程序的书写不符合语言的语法规则,这类错误可由编译程序发现。2.逻辑错误。指程序设计不当造成程序没有完成预期的功能,这类错误通过测试发现。3.运行异常。指程序设计对程序运行环境考虑不周全而造成的程序在运行中异常终止,如:内存空间不足、打开不存在的文件进行读操作、程序执行了除以0的指令等等。10.1
异常的概念和异常处理的基本思想
异常处理的概念:
程序运行中的运行异常是可以预料但不可避免的。对于运行异常不能简单地退出整个程序,特别是对大型程序更不能如此处理。因此为了保证程序的健壮性,必须在程序中对运行异常进行预见性处理。对运行异常进行预见性处理称为异常处理。
10.1
异常的概念和异常处理的基本思想
异常处理的基本思想:上述处理机制将正常处理与异常处理交织在一起,程序的易读性差。而且对于像构造函数、析构函数这类系统自动调用,又没有返回值的特殊函数,就没有办法利用返回值返回异常。if(b==0)cout<<“Divide0!”<<endl;elsecout<<Div(a,b);floatDiv(floata,floatb){returna/b;}10.1
异常的概念和异常处理的基本思想
异常处理的基本思想:在一个大型软件中,由于函数之间有着明确的分工和复杂的调用关系,发现错误的函数往往不具备处理错误的能力。这时它就引发一个异常,希望由它的调用者能够捕获这个异常并处理这个错误。如果调用者也不能处理这个错误,还可以继续传递给上级调用者去处理。这种传播会一直继续到异常被处理为止。如果程序始终没有处理这个异常,最终它会被传到C++运行系统那里。运行系统捕获异常后通常只是简单地终止这个程序。
异常传播方向
C++的异常处理机制使得异常的引发和处理不必在同一函数中,这样底层的函数可以着重解决应用问题,而不必过多地考虑对异常的处理。上层调用者则在适当的位置安排对不同类型异常的处理。10.1
异常的概念和异常处理的基本思想10.2异常处理机制
C++提供了一种以结构化的形式来描述异常处理过程的机制。该异常处理机制能够把程序的正常处理和异常处理逻辑分开表示,使得程序的异常处理结构清晰。通过异常集中处理的方法,解决异常处理问题。10.2异常处理机制
10.2.1异常处理的语法10.2.2异常处理接口声明10.2.3异常处理处理的嵌套10.2.4异常的重新抛出10.2.1异常处理的语法
异常处理机制的主要思想是:程序在结构上分为两个区域:异常抛出区:把可能造成异常的操作放在异常抛出区的try语句块中,如果try语句块中的某个操作在执行中产生了异常,则通过执行一个throw语句抛出一个异常对象。异常处理区:抛出的对象将由异常处理区的catch语句来捕获并处理。10.2.1异常处理的语法C++异常处理由try…throw…catch组成try语句块语法如下:try{复合语句}throw()函数语法格式如下:throw(异常类型表达式);catch语句格式如下:catch(异常类型声明){
复合语句}…catch(异常类型声明){
复合语句}一定要有”{}”10.2.1异常处理的语法其中:
1.异常类型可以是基本数据类型、构造数据类型、还可以是类类型,类型名后可以带变量(对象)名,这样就像函数的参数传递一样,可以将异常类型表达式的值传入。
2.异常类型还可以写…,表示可以捕获任意类型的异常,因此通常将catch(…)写在最后。
3.try和catch子句为复合语句,因此如果try和catch子句中只有一条语句,也必须用”{}”括起来。10.2.1异常处理的语法1.程序执行到try异常抛出区,执行try中的保护段代码。
2.如果执行保护段代码没有发生异常,就不执行throw()语句,控制跳过其后异常处理区catch语句块,执行后续语句。异常处理的执行过程如下:10.2.1异常处理的语法3.如果在执行try保护段(包括直接或间接调用)期间引发异常,则通过throw创建一个异常对象,并抛出异常,进入异常处理区。程序按catch出现的顺序依次进行异常类型匹配。如果找到类型匹配的catch,则该catch处理程序被执行。执行结束,程序转移到异常处理区的后续语句执行。如果没有找到类型匹配的catch,则继续检查外层的try块。一直到最外层的封闭的try块被检查完。
4.如果逐层始终没有找到匹配的处理程序,则自动运行系统terminate函数终止程序运行。注意:如果catch子句异常类型是基类,则该catch子句匹配该基类的所有派生类。因此如果要分别捕获基类和派生类类型异常,应该捕获派生类的catch子句列在前,捕获基类的catch子句列在后。10.2.1异常处理的语法[例10-1]处理除零异常。异常处理区中的各catch处理程序的顺序安排很重要。如果将上例的异常处理程序安排成下面形式,则catch(int)始终不被检查。catch(…){…//处理所有的异常}catch(int){ cout<<"exceptofdevidingzero.\n";}处理所有异常处理int异常10.2.2异常接口声明
可以在函数的声明中列出函数可能抛出的所有异常类型,称为异常接口声明。语法形式如下:
函数类型函数名(形参表)[throw([异常类型表])];其中:
1.“异常类型表”中列出函数可以抛出的各种异常类型名。
2.当函数声明中没有throw关键词,表明函数可以抛出任何异常;
3.当函数声明中有throw关键词,但没有“异常类型表”时,表明函数不抛出任何异常;[例10-2]带有异常接口声明的函数。
10.2.3嵌套的异常处理
在一个带异常处理的函数中调用另一个函数,而在另一个函数中产生异常。这样通过函数嵌套调用便形成了嵌套的异常处理。在这种情况下,嵌套的已成处理如右图所示[例10-3]带嵌套异常处理的一元二次方程求解。10.2.4异常的重新抛出
当catch语句捕获一个异常后,会出现两种情况:
1.可能不能处理,或不能完全处理异常。
2.完成某些操作后,该异常还须由上一级函数来处理。这时catch子句可以重新抛出(rethrow)该异常,把异常传递给函数调用链中更上级的另一个catch子句,由它进行进一步处理。10.2.4异常的重新抛出
重新抛出异常的语句是:
throw;
如例10-3中,resolution函数的B行,就是将异常再次抛出。注意:在使用throw重新抛出时,必须之前曾经抛出过异常,否则会出错。另外重新抛出的throw只能是在catch语句或者是catch调用的函数中。10.3
异常处理实例
—数组下标越界异常处理
C++标准库提供了一个异常基类exception。exception基类提供了what()虚函数,用户可以使用C++标准库中的异常类处理程序中的异常。也可以派生新类,重定义what()函数,以发出相应的异常信息。异常类层次中有一个out_of_range逻辑异常,专门用来处理数组下标越界。通过这个异常类能够很好地解决数组下标越界问题。[例10-4]标准库异常类处理数组下标越界异常。第10章异常处理谢谢补充:异常处理中的构造与析构
C++异常处理的真正能力,在于它具有为异常抛掷前构造的所有局部对象自动调用析构函数的能力。在程序中,找到一个匹配的catch异常处理后,如果catch子句的异常类型声明是一个引用,则其初始化方式是使该引用指向异常对象。当catch子句的异常类型声明参数被初始化后,栈的展开过程便开始了。这包括将从对应的try块开始到异常被抛掷处之间构造的(且尚未析构)的所有自动对象进行析构。析构的顺序与构造的顺序相反,然后程序从最后一个catch处理之后开始恢复运行。
C++标准库提供了一个异常类层次结构,用来报告C++标准库中的函数执行期间遇到的程序不正常情况。这些异常类也可以被用在用户编写的程序中,或被进一步派生来描述程序中的异常。
C++标准库中的异常类层次以exception作为基类。该基类提供了what()虚函数,在每个派生类中重定义,发出相应的异常信息。补充:C++标准库的异常处理
补充:C++标准库的异常处理
exception类的接口如下:namespacestd{//注意在名字空间域std中
classexception{public:exception()throw();//默认构造函数
exception(constexception&)throw();//复制构造函数
exception&operator=(constexception&)throw();
//复制赋值操作符
virtual~exception()throw();//析构函数
virtualconstchar*what()constthrow();
//返回一个C风格的字符串,目的是为抛出的异常提供文本描述
};}C++标准库异常类定义在四个头文件中:
1)<exception>头文件中定义了异常类exception;
2)<stdexcept>头文件中定义了几种常见的异常类。
3)<new>头文件中定义了bad-alloc异常类。当new无法分配内存时将抛出该异常类对象。
4)<type_info>头文件中定义了bad_cast异常类。当dynamic_cast失败时将抛出该异常类对象。标准异常类之间的关系:exception派生出runtime_error类、logic_error类、bad_cast类和bad_alloc类。由runtime_error派生出range_error、overflow_error、underflow_error;由logic_error派生出domain_error、invalid_argument、length_error、out_of_range。
补充:C++标准库的异常处理
补充:
C++标准库的异常处理C++标准库提供的逻辑异常:invalid_argument异常,接收到一个无效的实参,抛出该异常。out_of_range异常,使用一个超出有效范围的值,则抛出。length_error异常,报告试图生成一个超出该类型最大长度的对象。domain_error异常,用以报告域错误。以上四个异常是由logic_error类派生的。C++标准库提供的运行异常:range_error异常,报告内部计算中的范围错误。overflow_error异常,报告计算上溢错误。underflow_error异常,报告计算下溢错误。以上三个异常是由runtime_error类派生的。第10章异常处理谢谢![例10-1]处理除零异常。#include<iostream>usingnamespacestd;intDiv(intx,inty);intmain(){ try { cout<<"5/2="<<Div(5,2)<<endl; cout<<"8/0="<<Div(8,0)<<endl; cout<<"7/1="<<Div(7,1)<<endl; } catch(int){ cout<<"exceptofdevidingzero.\n"; } cout<<"thatisok.\n"; return0;}intDiv(intx,inty){ if(y==0) throwy; returnx/y;}程序运行结果:5/2=2exceptofdevidingzero.thatisok.[例10-2]带有异常接口声明的函数。#include<iostream>usingnamespacestd;voidfun(intx)throw(int,char,double);//fun()函数可以抛出三种异常类型voidfun(intx)throw(int,char,double){ if(x==0)throwx; if(x==1)throw'a'; if(x==2)throw(double)x;}intmain(){ try{ for(inti=1;i<4;i++) fun(i); } catch(int){ cout<<"catchint\n"; } catch(char){ cout<<"catchchar\n"; } catch(double){ cout<<"catchdouble\n"; } return0;}程序运行结果:catchchar[例10-3]带嵌套异常处理的一元二次方程求解。一元二次方程求解公式为:当a=0,b≠0,x=-c/b(10-1)x= (10-2)因此在求解过程中可能出现两种异常:表达式(10-1)和(10-2)中除数为0以及表达式(10-2)中b2-4ac<0。#include<iostream>#include<cmath>usingnamespacestd;structResult{ doublex1,x2;};Resultresolution(doublea,doubleb,doublec)throw(double);doublequotient(doublea,doubleb)throw(char*);intmain(){ doublea,b,c; Resultroot; cout<<"Inputa,b,c"; cin>>a>>b>>c; try{ root=resolution(a,b,c); cout<<"x1="<<root.x1<<",\tx2="<<root.x2<<endl; } catch(double){ cerr<<"Sqrtnegativateexception"<<endl; } catch(...){ cerr<<"Unexceptedorrethrowexception"<<endl; } return0;}Resultresolution(doublea,doubleb,doublec)throw(double){ Resulttempr; try{ if(a==0&&b!=0){ tempr.x1=tempr.x2=quotient(-c,b); returntempr; } if(b*b<4*a*c)throw(b); tempr.x1=quotient(-b+sqrt(b*b-4*a*c),2*a); tempr.x2=quotient(-b-sqrt(b*b-4*a*c),2*a); returntempr; } catch(char*Errs){ cerr<<Errs<<endl; //exit(0); //A //throw; //B }}doublequotient(doublea,doubleb)throw(char*){ if(b==0)throw("Divide0"); elsereturna/b;}程序运行结果:Inputa,b,c123SqrtnegativateexceptionInputa,b,c003Divide0x1=-6.98351e-251,x2=2.87248e-313[例10-4]标准库异常类处理数组下标越界异常#include<iostream>#include<string>#include<iomanip>#include<stdexcept>usingnamespacestd;constintDefaultArraySize=10;template<typenameelemType>classArray{public: explicit
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 水头志愿活动方案
- 榴莲推广活动方案
- 梦想演讲活动方案
- 植物角观摩活动方案
- 检察大竞赛活动方案
- 樱花节餐饮活动策划方案
- 河流保护活动方案
- 民族品牌公益活动方案
- 棋牌室促销活动方案
- 毕业合照活动策划方案
- 大学英语四六级词汇表
- 黑龙江省2024年普通高校招生体育类本科批院校专业组投档分数线(历史类)
- 水闸地基施工方案
- 企业数字化转型服务协议
- 《建立合适边界:亲子教育课件》
- DB37-T 4516-2022 高速公路边坡光伏发电工程技术规范
- 变电所设备更换申请报告
- 2023年遗传学考试题库(含答案)
- 课题申报参考:基于多模态大数据的大学生心理危机预警机制研究
- 《消费者行为学》教学大纲
- 《矿井扇风机》课件
评论
0/150
提交评论