C应用与开发案例教程下实用.pptx
有时候,你可能面临并非所有的事情都是完美的事实,偶有时候,你可能面临并非所有的事情都是完美的事实,偶而,甚至最好的计划也会失败。不管怎么说,是人就会犯错。而,甚至最好的计划也会失败。不管怎么说,是人就会犯错。为了防范运行时的错误,为了防范运行时的错误,C+环境给予程序员试运行的机会,环境给予程序员试运行的机会,如果运行失败,它提供了一个预防机制。异常处理就是这种如果运行失败,它提供了一个预防机制。异常处理就是这种机制。机制。异常是发生在运行期间的诸如零作分母、数组的溢出以及异常是发生在运行期间的诸如零作分母、数组的溢出以及空闲空间的耗尽这样的错误事件。假如这些错误没有被捕获,空闲空间的耗尽这样的错误事件。假如这些错误没有被捕获,则程序会突然地停止执行,而没有提供任何指示给使用者,则程序会突然地停止执行,而没有提供任何指示给使用者,告诉他发生了什么。处理这样的异常,不同的程序员有不同告诉他发生了什么。处理这样的异常,不同的程序员有不同的风格,这导致了代码的多样性。这种多样性随着用户自定的风格,这导致了代码的多样性。这种多样性随着用户自定义类的使用而增长,因为每一种这样的类都带有其潜在的特义类的使用而增长,因为每一种这样的类都带有其潜在的特定类的异常结构。定类的异常结构。当一个异常发生时,当一个异常发生时,C+以下列方式做出反应:以下列方式做出反应:1.发生异常的函数可以产生一个系统定义的消息;发生异常的函数可以产生一个系统定义的消息;8.1概述第1页/共237页8.1概述2.函数可以完全终止执行;3.函数可以跳过中间层继续执行其他的部分。C+语言提供内建的对于意外情况处理的支持,这就是异常处理。通过C+语言的异常处理,你的程序能够使意外的事件与高层次的执行上下文进行通信,它能够从这种异常事件中恢复过来。C+处理异常的机制是灵活的,因此它能处理任何类型的异常。在C+中,产生一个异常被称为引发一个异常。第2页/共237页 8.2 何时使用异常处理 在程序运行期间调用一个函数会产生三种结果。它们是:在程序运行期间调用一个函数会产生三种结果。它们是:1.正常执行正常执行 在执行过程中,函数正常地执行并返回到调用的程序中在执行过程中,函数正常地执行并返回到调用的程序中.一一些函数把结果代码返回给调用者。返回的代码表明执行的结些函数把结果代码返回给调用者。返回的代码表明执行的结果。果。2.错误执行错误执行 当调用者在变量传递过程中犯错或调用的函数超出上下文当调用者在变量传递过程中犯错或调用的函数超出上下文的范围时,会导致一个错误,这会终止程序的执行。的范围时,会导致一个错误,这会终止程序的执行。3.异常执行异常执行 在执行过程中出现异常的一种典型情况是内存不足;另一在执行过程中出现异常的一种典型情况是内存不足;另一种典型情况是一个种典型情况是一个I/O操作的异常。例如,当打开一个存在操作的异常。例如,当打开一个存在的文件时,存储媒介的设备驱动器可能会出错。这种情况不的文件时,存储媒介的设备驱动器可能会出错。这种情况不能通过简单的查找文件是否存在来处理,引发并捕捉异常是能通过简单的查找文件是否存在来处理,引发并捕捉异常是最佳的处理方法。最佳的处理方法。第3页/共237页 8.2 何时使用异常处理 在开发需要照顾意外情形的应用程序时,异常处理是必需的。发生在程序执行时的意外情形有:运行内存不够、资源分配错误、不能找到/打开文件等。假如这些错误没有被捕获,那么,在没有给予用户任何有关发生什么情况的提示下,程序将被中断。异常可以被定义为在程序执行中意外情况的出现和正常指令流的中断。第4页/共237页8.3 异常处理的基本语法 异常处理是C+的一个特征,它提供了处理运行期间异常的标准工具。一种一致性语法可以应用于这种目的,它能够被程序员很好的协调校正。一些常见的异常有分母为零、数组溢出以及NULL指针(即一个包含0值的指针)的引用。在C+语言中用try、throw和catch语句实现异常处理,在程序的某个函数中发现异常时使用throw表达式抛出这个异常,这个异常被抛给该函数的调用者,调用者用catch捕获该异常并进行相应的处理。当预测到某段程序将可能出现问题时,则该段程序放在try语句之后,使该段程序得以有机会抛出异常。第5页/共237页8.3.1 异常处理的语法 异常处理的语法如下:throw 表达式语法:throw 表达式 try 表达式语法:try 受保护的程序段语句 catch(异常类型)异常处理语句;catch(异常类型)异常处理语句;其中,catch括号中异常类型与throw抛出的异常类型相匹配,当某个异常发生后,catch语句将逐个被检查,直到某个异常类型与throw抛出的异常类型相匹配,然后执行catch后面的第6页/共237页8.3.1 异常处理的语法异常处理程序。若catch括号中是省略号(),则该catch可以捕获所有的异常类型,所以这样的语句一般放在所有catch语句的最后一个,否则其他catch语句就没有机会捕捉相应的错误类型了。当某个异常被捕捉并被相应的程序段处理后,系统将继续执行捕捉函数的其余部分。产生异常的函数和直到捕捉到异常的函数之间的所有调用链上的函数将从栈中删除。如果一个异常没有被任何函数捕捉到,则运行函数terminate将被调用,该函数的默认功能是调用abort函数终止程序的运行。一个异常处理的过程可以如下表示:void fun()int i;double f;第7页/共237页8.3.1 异常处理的语法 char c;/程序的其他部分 try /预期可能出现问题的地方,保护起来throwi;/如果出现问题1,抛出一个整数(只是假设)throwf;/如果出现问题2,抛出一个双精度数(只是假设)throwc;/如果出现问题3,抛出一个字符(只是假设)catch(intii)/相应处理catch(doubleff)第8页/共237页8.3.1 异常处理的语法/相应处理catch(charcc)/相应处理/程序其他部分【例8-1】#includevoidmain()try第9页/共237页8.3.1 异常处理的语法intage;coutage;if(age100|age1)throwInvalidage!;coutAfterthethrowstatementendl;catch(char*msg)coutError!msgendl;coutAfterthecatchhandlerendl;程序的输出结果为:第10页/共237页8.3.1 异常处理的语法 Enter the age::46After the throw statementAfter the catch handleEnter the age::116Error!Invalid age!After the catch handle第11页/共237页8.3.2 异常的类型 异常有两种类型:同步异常和异步异常。1.同步异常 发生在运行期间,并且能够使用throw表达式产生。仅有这种类型的异常能够使用C+中的异常处理器处理。控制不必返回异常引发处。2.异步异常 因为一个键盘或鼠标的中断而产生。C+程序不能使用try和catch语句直接处理这种类型的异常。一次不得不产生一个自动调用与键盘或鼠标中断相关的例程。第12页/共237页8.4 Try、catch和throw语句 在在C+语语言言中中执执行行异异常常处处理理的的是是Try、catch和和 throw语语句句。通通过过C+的的异异常常处处理理,你你的的程程序序能能够够探探测测到到异异常常事事件件并并从从中中恢复过来。恢复过来。一个包含一个包含try、catch和和 throw语句的程序的执行过程如下:语句的程序的执行过程如下:1.控控制制通通过过正正常常的的连连续续执执行行到到达达try语语句句,在在try模模块块内内的的语语句句被被保护执行;保护执行;2.如如果果在在被被保保护护的的执执行行期期间间没没有有异异常常被被引引发发,try模模块块之之后后的的catch语语句句不不会会执执行行。在在引引发发异异常常的的try模模块块后后面面的的最最后后的的catch语句之后继续执行;语句之后继续执行;3.如如果果在在被被保保护护的的执执行行过过程程中中有有一一个个异异常常被被引引发发,程程序序搜搜寻寻一一个能够处理被引发类型的异常的个能够处理被引发类型的异常的catch语句;语句;4.如如果果没没有有找找到到一一个个类类型型匹匹配配的的处处理理器器,那那么么调调用用预预定定义义的的运运行期间的函数行期间的函数terminate();第13页/共237页8.4 Try、catch和throw语句5.如果找到了类型匹配的catch处理器,初始化它的参数并执行catch处理器中的指令。如果程序终止,释放堆栈中的所有值。一个基类的处理器也能够处理它的子类的异常。如果在catch表达式中遇到了一个“”,它将处理所有的异常而不管它们的数据类型。【例8-2】#includevoidmain()coutbeforethethrowstatementendl;trythrow25.6f;/引发一个浮点值第14页/共237页8.4 Try、catch和throw语句catch(char*str)coutCaughtastringendl;catch(inti)coutCaughtanIntegerendl;catch(.)coutUnknowndatatypeendl;coutAfterthethrowstatementendl;第15页/共237页8.4 Try、catch和throw语句在上面的代码中,一个浮点值从try模块中被引发。然而,没有为接受一个浮点值而特意设计的catch处理器。因此程序的输出是:beforethethrowstatementUnkonwndatatypeAfterthethrowstatement新的运算符new引发了一个bad_alloc异常。新的头文件声明了bad_alloc类,它从异常类继承而来。What()函数在异常类中被声明。【例8-3】检查内存分配操作。#include#includevoidmain()第16页/共237页8.4 Try、catch和throw语句char*buff;trybuff=newchar1000000000;/声明在新的头文件中的新的运算符bad_alloc引发了一个类的对象catch(std:bad_alloc&obj)cout:obj.what()endl;该程序是关于一个try模块和与它相联系的catch处理器的第17页/共237页8.4 Try、catch和throw语句一个实例。该实例检查一个内存分配操作的错误,如果内存分配操作成功,则catch处理器不执行。在一个内存分配错误的情况下,程序的输出是:Exceptionraised:bad_alloc如果在一个try模块执行过程中没有引发异常,在try模块后的catch语句不被执行。程序将在引发异常的try模块之后的最后一条catch语句继续执行。控制器只能够通过一个引发的异常来输入一个catch处理器,而不能通过一个switch语句中的一个case标号来进行。在前面提到的实例中,在try模块后仅存在一个catch处理器。然而,并不是一直这样的。也会存在其他的catch处理器。如果throw语句准备仅引发内建的数据类型(在这种情况下使用字符型),catch处理器的数量不能超过语言支持第18页/共237页8.4 Try、catch和throw语句的内建数据类型的数量。为了解决这个问题,一个用户定义类型的不同的对象能够引发给处理器。如下例:【例8-4】#include#includeclassMyExceptionpublic:charcause21;MyException(char*in=0)strcpy(cause,in);第19页/共237页8.4 Try、catch和throw语句voidprintMessage()coutendlError:causeendl;classAclassintage;public:voidget()coutage;if(age100)第20页/共237页8.4 Try、catch和throw语句MyExceptione(Problemwithage);throwe;elsecoutCORRECTAGE!endl;voidmain()Aclassobject;第21页/共237页8.4 Try、catch和throw语句tryobject.get();catch(MyException&x)x.printMessage();【例8-5】异常的抛出和捕捉在同一函数中。#include#includeclassPerson第22页/共237页8.4 Try、catch和throw语句protected:charName20;/姓名intOld;/年龄unsignedlongID;/身份证号charSex;/性别public:Person(char*theName,inttheOld,unsignedlongtheId,chartheSex);/类Person的构造函数;Person:Person(char*theName,inttheOld,unsignedlongtheId,chartheSex)if(Name=)/有效性检查第23页/共237页8.4 Try、catch和throw语句throwInvalidPersonsname!;if(Old200)/有效性检查throwOld;if(Sex!=M)&(Sex!=m)&(Sex!=F)&(Sex!=f)/有效性检查throwSex;voidfun()trycoutfunline1endl;Personp1(zhang,43,1234566L,M);/类Person的对象p1coutfunline2endl;Personp2(,-1,22222222L,F);/类Person的对象p2coutfunline3endl;第24页/共237页8.4 Try、catch和throw语句Personp3(,-1,33333333L,M);/类Person的对象p3coutfunline4endl;Personp4(,-1,44444444L,F);/类Person的对象p4catch(char)/捕捉错误并进行处理coutInvalidSex!endl;catch(int)/捕捉错误并进行处理coutInvalidOld!endl;catch(char*Msg)/捕捉错误并进行处理第25页/共237页8.4 Try、catch和throw语句coutInvalidName!endl;voidmain()coutbeforefun.endl;fun();coutendfun.endl;coutinthemainfunction!endl;在本程序中,异常的抛出和捕捉都在函数fun中,在实际应用中,异常的引发和处理一般在不同函数中,这样低层函数可以专注于具体问题,上层调用函数可以在恰当的位置设计对不同类型第26页/共237页8.4 Try、catch和throw语句的异常进行各种处理而不考虑低层函数是如何产生这个异常的。【例8-6】对【例8-5】稍加改动,使异常的抛出和捕捉在不同函数中进行。【例8-6】异常的抛出和捕捉在不同函数中。#include#includeclassPersonprotected:charName20;/姓名intOld;/年龄unsignedlongID;/身份证号charSex;/性别第27页/共237页8.4 Try、catch和throw语句public:Person(char*theName,inttheOld,unsignedlongtheId,chartheSex);/类Person的构造函数;Person:Person(char*theName,inttheOld,unsignedlongtheId,chartheSex)if(Name=)/有效性检查throwInvalidPersonsname!;if(Old200)/有效性检查throwOld;if(Sex!=M)&(Sex!=m)&(Sex!=F)&(Sex!=f)/有效性检查第28页/共237页8.4 Try、catch和throw语句throwSex;voidfun()coutfunline1endl;Personp1(zhang,43,1234566L,M);/类Person的对象p1coutfunline2endl;Personp2(,-1,22222222L,F);/类Person的对象p2coutfunline3endl;Personp3(,-1,33333333L,M);/类Person的对象p3coutfunline4endl;Personp4(,-1,44444444L,F);/类Person的对象p4第29页/共237页8.4 Try、catch和throw语句voidmain()trycout”beforefun”endl;fun();cout”endfun”endl;catch(char)/捕捉错误并进行处理coutInvalidSex!endl;catch(int)/捕捉错误并进行处理第30页/共237页8.4 Try、catch和throw语句coutInvalidOld!endl;catch(char*Msg)/捕捉错误并进行处理coutInvalidName!endl;coutendl;coutinthemainfunction!endl;下面这个例子演示了如何用异常处理纠正程序运行期错误。【例8-7】纠正如下程序运行期错误。#include#includeclassString第31页/共237页8.4 Try、catch和throw语句private:char*str;public:String()str=0;String(char*inString)str=newcharstrlen(inString)+1;strcpy(str,inString);voidreplace(charsearch,charrepl)第32页/共237页8.4 Try、catch和throw语句intcounter;for(counter=0;strcounter!=0;counter+)if(strcounter=search)strcounter=repl;voiddisplay()coutstr;第33页/共237页8.4 Try、catch和throw语句;voidmain()StringstrObject;/该对象不包含任何东西strObject.replace(+,);strObject.display();上面的代码产生下面的运行期错误:Segmentationfault(coredumped)分析:要想纠正如上程序运行期错误,首先要找到出现异常的原因,然后采用异常处理机制去处理异常。因此,下面分两步进行介绍。1标识异常的原因根据分析知道,在main()函数中,String类的一个空对象被第34页/共237页8.4 Try、catch和throw语句创建。replace()函数将遍历字符串直到空字符(0)出现,但如果字符串为空,那么操作失败。2标识异常处理的机制采用try、throw、catch语句进行处理。修改上面程序得如下程序:#include#includeclassStringprivate:char*str;intcheck()if(str=NULL)第35页/共237页8.4 Try、catch和throw语句return0;elsereturn1;public:String()str=0;String(char*inString)str=newcharstrlen(inString)+1;strcpy(str,inString);第36页/共237页8.4 Try、catch和throw语句voidreplace(charsearch,charrepl)if(check()=0)throwNULLpointerexception;intcounter;for(counter=0;strcounter!=0;counter+)if(strcounter=search)strcounter=repl;第37页/共237页8.4 Try、catch和throw语句voiddisplay()coutstr;voidmain()StringstrObject;/对象不能包含任何的trytrystrObject.replace(+,);/引起replace函数异常strObject.display();第38页/共237页8.4 Try、catch和throw语句catch(char*message)coutException:messageendl;程序的输出结果如下:Exception:NULLpointerexception第39页/共237页8.5 标准C+库中的异常类标准C+库中包含9个异常类,它们可以分为运行时异常和逻辑异常:length_error/运行时异常,长度异常domain_error/运行时异常,域异常out_of_range_error/运行时异常,越界异常invalid_argument/运行时异常,参数异常range_error/逻辑异常,范围异常overflow_error/逻辑异常,溢出(上)异常underflow_error/逻辑异常,溢出(下)异常标准C+库中的这些异常类并没有全部被显式使用,因为C+标准库中很少发生异常,但是这些标准C+库中的异常类可以为编程人员,特别是自己类库的开发者提供一个指导。下面程序简单说明C+标准异常类的使用。【例8-8】演示标准异常类的使用。第40页/共237页8.5 标准C+库中的异常类#include#includeusingnamespacestd;voidmain()tryexceptiontheError;/声明一个C+标准异常类的对象throw(theError);/抛出该异常类的对象catch(constexception&theError)/捕捉C+标准异常类的对象couttheError.what()endl;/用what()成员函数显示出错原因第41页/共237页8.5 标准C+库中的异常类trylogic_errortheLogicError(LogicError!);/声明一个C+标准异常类logic_error的对象throw(theLogicError);/抛出该异常类的对象catch(constexception&theError)/捕捉C+标准异常类的对象couttheError.what()endl;/用what()成员函数显示出错原因第42页/共237页8.6 程序实例【例8-9】设计一个异常Exception抽象类,在此基础上派生一个OutOfMemory类响应内存不足,派生一个RangeError类响应输入的数不在指定范围内,实现并测试这两个类。程序如下:/EG8_8.CPP#includeclassExceptionpublic:Exception()virtualException()第43页/共237页8.6 程序实例virtualvoidPrintError()=0;classOutOfMemory:publicExceptionpublic:OutOfMemory()OutOfMemory()第44页/共237页8.6 程序实例virtualvoidPrintError();voidOutOfMemory:PrintError()coutOutofMemory!endl;classRangError:publicExceptionpublic:RangError(unsignedlongnumber)BadNum=number;第45页/共237页8.6 程序实例RangError()virtualvoidPrintError();virtualunsignedlongGetNumber()returnBadNum;virtualvoidSetNumber(unsignedlongnumber)BadNum=number;第46页/共237页8.6 程序实例private:unsignedlongBadNum;voidRangError:PrintError()coutNumberOutofrange.YouusedGetNumber()!n;voidfn1();unsignedint*fn2();voidfn3(unsignedint*);voidmain()try第47页/共237页8.6 程序实例fn1();catch(Exception&theException)theException.PrintError();unsignedint*fn2()unsignedint*n=newunsignedint;if(n=0)throwOutOfMemory();第48页/共237页8.6 程序实例returnn;voidfn1()unsignedint*p=fn2();fn3(p);coutThenumberis:*pendl;deletep;voidfn3(unsignedint*p)longNumber;coutNumber;第49页/共237页8.6 程序实例if(Number1000|Number0)throwRangError(Number);*p=Number;程序的输出结果为:Enteraninteger(0-1000):78Thenumberis:78Enteraninteger(0-1000):1500Numberoutofrange.Youused1500!下面给出一个接近实用的例子,假设开发一个人员管理系统,并且声明了人这个基本类Person,它包含姓名、性别、年龄、证件号码等数据,我们可以事先估计一下可能出现的异常情况,如用户忘记输入姓名,年龄不在正常范围内、证件号码不符合要求、性别不符合要求等等,这要求有一个可以报告这类错误第50页/共237页8.6 程序实例的类InvalidPerson。同时,用户输入数据进行处理完成后需要存盘,下一次可以从磁盘中调出这些数据,这个过程中可能的异常是输入输出文件打开出错、输入数据被破坏等,要求有一个可以报告错误的类IOError。看下面的例子并体会异常处理的用法:【例8-10】人员管理系统中常用的异常处理。/EG8_9.H#ifndefEG8_9.H#defineEG8_9.Husingnamespacestd;classPerson;classError/声明出错类第51页/共237页8.6 程序实例public:Error(constchar*theWhere,constchar*theWhy):why(theWhy),where(theWhere)virtualvoiddisplay(ostream&out)const;/显示出错内容protected:conststringwhy;/错误原因conststringwhere;/错误地点;#endif/EG8_9.CPP#include#include第52页/共237页8.6 程序实例#include#EG8_9.HclassInvalidPerson:publicError/从类Error派生类InvalidPersonpublic:InvalidPerson(constPerson*thePerson,constchar*theWhy):Error(Person:InvalidCheck,theWhy),pPerson(thePerson)/InvalidPerson类构造函数virtualvoiddisplay(ostream&out)const;/派生类中的出错内容显示protected:constPerson*pPerson;/派生类中新增数据成员;classIOError:publicError/从类Error派生类IOError第53页/共237页8.6 程序实例public:IOError(constchar*theWhere,constchar*theWhy,constchar*theFileName):/IOError构造函数Error(theWhere,theWhy),FileName(theFileName)virtualvoiddisplay(ostream&out)const;/派生类中的出错内容显示protected:StringFileName;/文件名;classPersonpublic:第54页/共237页8.6 程序实例Person(conststring&theName,inttheOld,unsignedlongtheId,chartheSex);/Person类构造函数voiddisplay(ostream&out)const;/类Person的显示函数voidoutput(ostream&out)const;/类Person的输出函数staticPerson*input(istream&in);/类Person的输出函数voidInvalidCheck()const;/类Person的有效性检查protected:stringName;/姓名intOld;/年龄unsignedlongId;/身份证号码charSex;/性别;ostream&operator(ostream&out,constPerson&thePerson);/重载运算符第55页/共237页8.6 程序实例voidError:display(ostream&out)const/Error:display函数的实现out!ErrorRepurt-where:whyendl;/显示错误原因和地点voidInvalidPerson:display(ostream&out)const/InvalidPerson:display函数的实现Error:display(out);/调用基类的显示函数outPersonobject=(*pPerson)endl;/显示本类的新增特性voidIOError:display(ostream&out)const/IOError:display函数的实现第56页/共237页8.6 程序实例Error:display(out);/调用基类的显示函数outFile=FileNameendl;/显示本类的新增特性Person:Person(const string&theName,int theOld,unsigned long theId,chartheSex):Name(theName),Sex(theSex),Old(theOld),ID(theId)/Person类构造函数voidPerson:InvalidCheck()const/Person:InvalidCheck函数的实现if(Name.length()=0)/如果姓名为空,人员信息无效throwInvalidPerson(this,Invalidpersonsname);第57页/共237页8.6 程序实例/抛出InvalidPersonif(Old200)/如果人员年龄不在0-200之间,该人员信息无效throwInvalidPerson(this,InvalidpersonsOld);/抛出InvalidPersonif(Id0L)/如果身份证号码小于0,该人员信息无效throwInvalidPerson(this,InvalidpersonsId);/抛出InvalidPersonif(Sex!=M)&(Sex!=m)(Sex!=F)&(Sex!=f)/如果性别不是字符“M、m、F、f”,该人员信息无效第58页/共237页8.6 程序实例throwInvalidPerson(this,InvalidpersonsSex);/抛出InvalidPersonvoidPerson:display(ostream&out)const/Person:display函数的实现outName-Old-ID-Sex;/输出人员信息if(out.fail()/如果输出文件出错,则抛出IOErrorthrowIOError(Person:display),Outputfile,displayerror);第59页/共237页8.6 程序实例voidPerson:output(ostream&out)const/Person:output函数的实现InvalidCheck();/首先进行有效性检查,该函数在对象无效时可以抛出InvalidPersonoutNameOldIDSexn;/输出人员信息if(out.fail()/如果输出文件出错,则抛出IOErrorthrowIOError(Person:output),Outputfile,outputerror);第60页/共237页8.6 程序实例voidPerson:input(istream&in)const/Person:input函数的实现Person*TempPerson=0;/用于保存从in流中输入的对象stringTempPersonName;/保存从in流中输入的对象数据intTempPersonOld;unsignedlongTempPersonID;charTempPersonSex;tryif(in.get()!=);/将到 为止的流 in中内容保存到 TempPersonName中 inTempPersonOldTempPersonIDTempPersonSex;/从流in中依次输入到各个变量中in.get();/略过本行中剩余部分,到达下一行TempPerson=newPerson(TempPersonName,TempPersonOld,TempPersonID,TempPersonSex);第62页/共237页8.6 程序实例/用于输入数据构造临时对象TempPerson-InvalidCheck();/有效性检查catch(Error&theError)/捕捉错误进行初步处理coutErrorininput:endl;theError.display(cout);/显示错误deleteTempPerson;/删除该临时对象TempPerson=(Person*)0;throwError(Person:input,inputerror);/抛出Error类的对象returnTempPerson;第63页/共237页8.6 程序实例/EG8_9.CPP#include#include#include#EG8_9.Hostream&operator(ostream&out,constPerson&thePerson);voidOutputPersons(char*theFileName);voidInputPersons(char*theFileName);voidmain()tryOutputPerson(d:C+tempperson.txt);/将类Person的若干个对象输出到文件中,可放于自己指定的目录下第64页/共237页8.6 程序实例InputPerson(d:C+tempperson.txt);/从文件中输入类Person对象并显示catch(Error&theError)/捕捉错误类型,由于InvalidPerson和类IOError都是类Error的/子类,所以在此处也可以捕捉到这两种错误类型coutFatalerrorinprogram:endl;theError.display(cout);/错误信息显示ostream&operator(ostream&out,c