第11章 异常处理_第1页
第11章 异常处理_第2页
第11章 异常处理_第3页
第11章 异常处理_第4页
第11章 异常处理_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第11章

异常处理11.1异常处理概述11.2异常处理的基本思想11.3异常处理的实现11.4标准C++库中的异常类11.5多路捕获11.6含有异常的程序设计11.1异常处理概述程序可能按编程者的意愿终止,也可能因为程序中发生了错误而终止。程序的错误有两种,一种是编译错误,即语法错误。如果使用了错误的语法、函数、结构和类,程序就无法被生成运行代码。另一种是在运行时发生的错误,它分为不可预料的逻辑错误和可以预料的运行异常。异常处理机制是用于管理程序运行期间错误的一种结构化方法。所谓结构化是指程序的控制不会由于产生异常而随意跳转。异常处理机制将程序中的正常处理代码与异常处理代码显式区别开来,提高了程序的可读性。

返回首页11.2异常处理的基本思想异常的基本思想是:

(1)实际的资源分配通常在程序的低层进行,如上图中的F3()。(2)当操作失败、无法分配内存或无法打开一个文件时,在逻辑上如何进行处理通常在程序的高层,如上图中的F1(),中间还可能有与用户的对话。(3)异常为从分配资源的代码转向处理错误状态的代码提供了一种表达方式。如果还存在中间层次的函数,如上图中的F2(),则为它们释放所分配的内存提供了机会,但这并不包括传递错误状态信息的代码。返回首页图11-1异常处理示意图返回本节11.3异常处理的实现11.3.1异常处理的语法11.3.2异常处理机制返回首页C++语言异常处理机制的基本思想是将异常的检测与处理分离。当在一个函数体中检测到异常条件存在,但无法确定相应的处理方法时,将引发一个异常,并由函数的直接或间接调用检测并处理这个异常。这一基本思想用3个保留字实现:throw、try和catch。其作用是:(1)try:标识程序中异常语句块的开始。(2)throw:用来创建用户自定义类型的异常错误。(3)catch:标识异常错误处理模块的开始。

11.3.1异常处理的语法在C++程序中,任何需要检测异常的语句(包括函数调用)都必须在try语句块中执行,异常必须由紧跟在try语句后面的catch语句来捕获并处理。因而,try与catch总是结合使用。throw、try和catch语句的一般语法如下:

throw<表达式>;try{ //try语句块}catch(类型1参数1){ //针对类型1的异常处理}catch(类型2参数2){ //针对类型2的异常处理}…catch(类型n参数n){ //针对类型n的异常处理}try子句后的复合语句是代码的保护段。如果预料某段程序代码(或对某个函数的调用)有可能发生异常,就将它放在try子句之后。如果这段代码(或被调函数)运行时真的遇到异常情况,其中的throw表达式就会抛掷这个异常。catch子句后的复合语句是异常处理程序,“捕获”(处理)由throw表达式抛掷的异常。异常类型说明部分指明该子句处理的异常的类型,它与函数的形参是类似的,可以是某个类型的值,也可以是引用。

例11-1:异常处理示例程序。

#include<iostream.h>voidmain(){char*ptr;try //异常模块{

if((ptr=newchar[64*1024])==NULL)throw"NotEnoughMemory!";}catch(char*str) //异常错误处理模块{ //……错误处理代码

cout<<"Exception:"<<str<<endl;}}异常处理的执行过程如下:

(1)控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。(2)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行,程序从异常被抛掷的try块后跟随的最后一个catch子句后面的语句继续执行下去。(3)如果在保护段执行期间或在保护段调用的任何函数中(直接或间接的调用)有异常被抛掷,则从通过throw运算数创建的对象中创建一个异常对象(这隐含指可能包含一个拷贝构造函数)。

(4)如果匹配的处理器未找到,则函数terminate将被自动调用,而函数terminate的默认功能是调用abort终止程序。(5)如果找到了一个匹配的catch处理程序,且它通过值进行捕获,则其形参通过拷贝异常对象进行初始化。

例11-2:阅读下列程序,写出运行结果。

#include<iostream.h>voidExcp();classEx{public: Ex(){}; ~Ex(){};};classDemo{public: Demo() //构造函数 {

cout<<"CreateingaDemoobject."<<endl; }~Demo() //析构函数 {

cout<<"DeletingDemoobject."<<endl; }};voidExcp(){DemoA; //定义一个对象

cout<<"Excpfunctionthrowinganexception!"; cout<<endl; throwEx(); //创建成一个异常}voidmain(){ try { cout<<"NowcallExcpfunction."<<endl; Excp(); } catch(Exa) //捕捉Ex类异常 {

cout<<"AnExexceptionoccurred."<<endl; } catch(...) {

cout<<"Someotherexceptionoccurred."; cout<<endl; }}此程序的运行结果为:NowcallExcpfunction.CreatingaDemoobject.Excpfunctionthrowinganexception!DeletingDemoobject.AnExexceptionoccurred.返回本节11.3.2异常处理机制(1)try分程序必须出现在前,catch紧跟出现在后。catch之后的圆括号中必须含有数据类型,捕获是利用数据类型匹配实现的。(2)如果程序内有多个异常错误处理模块,则当异常错误发生时,系统自动查找与该异常错误类型相匹配的catch模块,查找次序为catch出现的次序。(3)如果异常错误类型为C++的类,并且该类有其基类,则应该将派生类的错误处理程序放在前面,基类的错误处理程序放在后面。(4)如果一个异常错误发生后,系统找不到一个与该错误类型相匹配的异常错误处理模块,则调用预定义的运行时刻终止函数,默认情况下是abort。例11-3:定义一个异常类CException,有成员函数Reason()用来显示异常的类型,定义函数fun()触发异常,在主函数的try模块中调用fun(),在catch模块中捕获异常,观察程序的执行过程。#include<iostream.h>classCException{public: CException(){} ~CException(){} constchar*Reason()const{return"CException类中的异常。";}

};

voidfun(){cout<<"在子函数中触发CException类异常"<<endl; throwCException();}

voidmain(){ cout<<"进入主函数"<<endl; try { cout<<"在try模块中,调用子函数"<<endl; fun(); } catch(CExceptionE) {cout<<"在catch模块中,捕获到CException类型异常:";

cout<<E.Reason()<<endl; } catch(char*str) { cout<<"捕获到其他类型异常:"<<str<<endl; } cout<<"回到主函数,异常已被处理。"<<endl;}程序的运行结果为:进入主函数在try模块中,调用子函数在子函数中触发CException类异常在catch模块中,捕获到CException类型异常:CException类中的异常。回到主函数,异常已被处理。例11-4:设计一个异常Exception抽象类,在此基础上派生一个OutOfMemory类响应内存不足,一个RangeError类响应输入的数不在指定的范围内,实现并测试这几个类。#include<iostream.h>

classException{public: Exception(){} virtual~Exception(){} virtualvoidPrintError()=0;};

classOutOfMemory:publicException{public: OutOfMemory(){} ~OutOfMemory(){}virtualvoidPrintError();};

voidOutOfMemory::PrintError(){ cout<<"OutofMemory!"<<endl;}

classRangeError:publicException{public: RangeError(unsignedlongnumber){BadNum=number;} ~RangeError(){}virtualvoidPrintError(); virtualunsignedlongGetNumber(){returnBadNum;} virtualvoidSetNumber(unsignedlongnumber){BadNum=number;}private: unsignedlongBadNum;};

voidRangeError::PrintError(){ cout<<"Numberoutofrange.Youused"<<GetNumber()<<"!"<<endl;}

voidfun1();unsignedint*fun2();voidfun3(unsignedint*);intmain(){ try {fun1();}

catch(Exception&theException) { theException.PrintError(); } return0;}

voidfun1(){ unsignedint*p=fun2(); fun3(p); cout<<"Thenumberis:"<<*p<<endl; deletep;}unsignedint*fun2(){ unsignedint*n=newunsignedint; if(n==0) throwOutOfMemory(); returnn;}

voidfun3(unsignedint*p){ longNumber; cout<<"Enteraninteger(0~999):"; cin>>Number;if(Number>999||Number<0) throwRangeError(Number); *p=Number;}程序运行结果为:Enteraninteger(0~999):7↙Thenumberis:7Enteraninteger(0~999):2004↙Numberoutofrange.Youused2004!例11-5:编写用户自定义的终止函数。#include<iostream.h>#include<eh.h>#include<process.h>voidmyterm(){ cout<<"Thisismyterminater."<<endl; … //其他代码

exit(-1);};intmain(){ … //其他代码

try {set_terminate(myterm); //传递终止函数名 … //其他代码

throw"Exception:……."; } catch(inti) { … //其他代码 }

return0;}返回本节11.4标准C++库中的异常类标准C++库中包含9个异常类,它们可以分为运行时异常和逻辑异常:

length_error //运行时长度异常domain_error //运行时域异常out_of_range_error //运行时越界异常invalid_argument //运行时参数异常range_error //逻辑异常,范围异常overflow_error //逻辑异常,溢出(上)异常underflow_error //逻辑异常,溢出(下)异常返回首页下面程序简单说明C++异常标准类exception和logic_error的使用方法。例11-6:演示标准异常类的使用。#include<iostream.h>#include<exception.h>usingnamespacestd;voidmain{ try { exceptiontheError; //声明一个C++标准异常类的对象

throw(theError); //抛出该异常类的对象 }catch(constexception&theError) //捕捉C++标准异常类的对象 {

cout<<theError.what()<<endl; } try { logic_errortheLogicError(“LogicError!”); //声明一个C++标准异常类(logic_error)的对象

throw(theLogicError); //抛出该异常类对象 }

catch(constexception&theLogicError) //捕捉C++标准异常类的对象 {

cout<<theLogicError.what()<<endl; //用what成员函数显示出错的原因 }}返回本节11.5多路捕获很多程序可能有若干不同种类的运行错误,它们可以使用异常处理机制,每种错误可与一个类,一种数据类型或一个值相关。这样,在程序中就会出现多路捕获。例11-7:操作string类对象时,预设两个异常。#include<iostream.h>#include<string.h>classString{public: String(char*,int) classyichang1//异常类1 {返回首页public: yichang1(intj):index(j){} intindex; }; classyichang2{};//异常类2

char&operator[](intk) { if(k>=0&&k<len) returnp[k]; throwyichang1(k); }private: char*p; intlen; staticintmax;};intString::max=20;String::String(char*str,intsi){ if(si<0||si>max) throwyichang2(); p=newchar[si]; strncpy(p,str,si); len=si;}voidg(String&str){ intnum=10; for(intn=0;n<num;n++) cout<<str[n]; cout<<endl;}voidf(){ //代码区1

try { //代码区2

Strings("abcdefghijklmnop",10); g(s); } catch(String::yichang1r) { cerr<<"->outofrange:"<<r.index<<en

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论