版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第七讲异常处理异常处理异常处理标准程序库异常处理综合实例异常安全性原则智能指针异常处理的基本思想异常处理函数f()捕获并处理异常函数h()引发异常函数g()……调用者异常传播方向调用关系发现错误的函数往往不具备处理错误的能力,这时它就引发一个异常,希望调用者捕获并处理这个错误。如果调用者也不能处理这个错误,还可以继续传递给上级调用者去处理,这种传播会一直继续到异常被处理为止。如果程序始终没有处理这个异常,最终它会被传到C++运行系统,运行系统捕获异常后通常只是简单地终止这个程序。异常处理的语法异常处理抛掷异常的程序段......throw表达式;......捕获并处理异常的程序段try
复合语句catch(异常声明)复合语句catch(异常声明)复合语句
…保护段异常处理程序C++的异常处理机制使得异常的引发和处理不必在同一函数中,这样底层的函数可以集中精力解决具体问题,而不必过多地考虑对异常的处理异常是一种包含错误信息的对象需要抛出的异常对象或变量即抛出异常的代码区域包含异常类型和异常参数,与函数形参类似如果异常声明是(…),表示该子句可以处理所有类型的异常,这样的子句必须放在最后。异常处理的语法异常处理若有异常则(系统或用户)通过throw操作创建一个异常对象并抛掷将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句,然后执行try块内的保护段如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去否则,catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛掷异常)如果当前函数没有匹配的catch子句,或异常抛出点本身不在任何try子句内,则结束当前函数的执行,回到当前函数的调用点,把调用点作为异常的抛出点,然后重复这一过程,直到异常成功地被一个catch语句捕获如果匹配的处理器始终未找到,则运行库函数terminate将被自动调用,其缺省功能是调用abort终止程序处理除零异常异常处理#include<iostream>usingnamespacestd;intdivide(intx,inty){ if(y==0)
throwx; returnx/y;}intmain(){ try { cout<<"5/2="<<divide(5,2)<<endl; cout<<"8/0="<<divide(8,0)<<endl; cout<<"7/1="<<divide(7,1)<<endl; }catch(inte) { cout<<e<<"isdividedbyzero!"<<endl; } cout<<"Thatisok."<<endl; return0;}结果如下:5/2=28isdividedbyzero!Thatisok.异常接口声明异常处理可以在函数的声明中列出这个函数可能抛掷的所有异常类型例如:
voidfun()throw(A,B,C,D);若无异常接口声明,则此函数可以抛掷任何类型的异常不抛掷任何类型异常的函数声明如下:voidfun()throw();表明函数fun只能抛掷类型A、B、C、D及其子类型的异常异常处理中的构造与析构异常处理找到一个匹配的catch异常处理后初始化异常参数将从对应的try块开始到异常被抛掷处之间构造(且尚未析构)的所有自动对象(即位于堆栈中的对象)进行析构。这一过程称为栈的解旋(unwinding)从最后一个catch子句之后开始恢复执行示例:使用带析构语义的类的C++异常处理异常处理#include<iostream>#include<string>usingnamespacestd;classMyException{public: MyException(conststring&message):message(message){} ~MyException(){}
conststring&getMessage()const{returnmessage;}private: stringmessage;};classDemo{public: Demo(){cout<<"ConstructorofDemo"<<endl;} ~Demo(){cout<<"DestructorofDemo"<<endl;}};示例:使用带析构语义的类的C++异常处理异常处理voidfunc()throw(MyException){ Demod; cout<<"ThrowMyExceptioninfunc()"<<endl;
throwMyException("exceptionthrownbyfunc()");}intmain(){ cout<<"Inmainfunction"<<endl; try { func(); }catch(MyException&e) { cout<<"Caughtanexception:"<<e.getMessage()<<endl; } cout<<"Resumetheexecutionofmain()"<<endl; return0;}示例:使用带析构语义的类的C++异常处理异常处理结果如下:InmainfunctionConstructorofDemoThrowMyExceptioninfunc()DestructorofDemoCaughtanexception:exceptionthrownbyfunc()Resumetheexecutionofmain()异常处理异常处理标准程序库异常处理综合实例异常安全性原则智能指针标准程序库异常处理range_erroroverflow_errorunderflow_errorexceptiondomain_errorinvalid_argumentlength_errorios_base::failurelogic_errorbad_typeidbad_exceptionbad_castruntime_errorbad_allocout_of_range标准程序库的异常类标准程序库异常处理exception:标准程序库异常类的公共基类logic_error表示可以在程序中被预先检测到的异常如果小心地编写程序,这类异常能够避免runtime_error表示难以被预先检测的异常三角形面积计算标准程序库异常处理编写一个计算三角形面积的函数,函数的参数为三角形三边边长a、b、c,可以用Heron公式计算:设,则三角形面积
#include<iostream>#include<cmath>#include<stdexcept>usingnamespacestd;//给出三角形三边长,计算三角形面积doublearea(doublea,doubleb,doublec)throw(invalid_argument){ //判断三角形边长是否为正
if(a<=0||b<=0||c<=0)
throwinvalid_argument("thesidelengthshouldbepositive"); //判断三边长是否满足三角不等式
if(a+b<=c||b+c<=a||c+a<=b)
throwinvalid_argument("thesidelengthshouldfitthetriangleinequation"); //由Heron公式计算三角形面积
doubles=(a+b+c)/2; returnsqrt(s*(s-a)*(s-b)*(s-c));}三角形面积计算标准程序库异常处理intmain(){ doublea,b,c; //三角形三边长
cout<<"Pleaseinputthesidelengthsofatriangle:"; cin>>a>>b>>c; try { doubles=area(a,b,c); //尝试计算三角形面积
cout<<"Area:"<<s<<endl; }catch(exception&e) { cout<<"Error:"<<e.what()<<endl; } return0;}三角形面积计算标准程序库异常处理运行结果1:Pleaseinputthesidelengthsofatriangle:345Area:6运行结果2:Pleaseinputthesidelengthsofatriangle:055Error:thesidelengthshouldbepositive运行结果2:Pleaseinputthesidelengthsofatriangle:124Error:thesidelengthshouldfitthetriangleinequation三角形面积计算标准程序库异常处理异常处理异常处理标准程序库异常处理综合实例异常安全性原则智能指针综合实例——对个人银行账户管理程序的改进本例中,在构造或输入一个Date对象时如发生了错误,直接使用标准程序库中的runtime_error构造异常并抛出;在账户类中如发生了错误,希望异常信息能够标识是哪个账户发生了错误。本程序中创建了一个类AccountException,该类从runtime_error派生,该类中保存了一个Account型常指针,指向发生错误的账户,这样在主函数中,输出错误信息的同时也可以将账号输出。综合实例——对个人银行账户管理程序的改进//date.cpp,仅列出与以前不同的内容,下同#include"date.h"#include<iostream>#include<stdexcept>usingnamespacestd;Date::Date(intyear,intmonth,intday):year(year),month(month),day(day){ if(day<=0||day>getMaxDay())
throwruntime_error("Invaliddate"); intyears=year-1; totalDays=years*365+years/4-years/100+years/400+DAYS_BEFORE_MONTH[month-1]+day; if(isLeapYear()&&month>2)totalDays++;}istream&operator>>(istream&in,Date&date){ intyear,month,day; charc1,c2; in>>year>>c1>>month>>c2>>day; if(c1!='-'||c2!='-')
throwruntime_error("Badtimeformat");
date=Date(year,month,day); returnin;}综合实例——对个人银行账户管理程序的改进//account.h#ifndef__ACCOUNT_H__#define__ACCOUNT_H__#include"date.h"#include"accumulator.h"#include<string>#include<map>#include<istream>#include<stdexcept>//account.h中增加了以下类,其它各类的定义与之前相同,不再重复给出classAccountException:publicstd::runtime_error{private: constAccount*account;public: AccountException(constAccount*account,conststd::string&msg) :runtime_error(msg),account(account){}
constAccount*getAccount()const{returnaccount;}};#endif//__ACCOUNT_H__综合实例——对个人银行账户管理程序的改进//account.cpp中仅以下成员函数的实现与之前不同,其它内容皆与之相同voidAccount::error(conststring&msg)const{
throwAccountException(this,msg);}//以下仅主函数的实现与之前不同,其它皆与之相同intmain(){ Datedate(2008,11,1); //起始日期
Controllercontroller(date); stringcmdLine; constchar*FILE_NAME="commands.txt";
ifstreamfileIn(FILE_NAME); //以读模式打开文件
if(fileIn) //如果正常打开,就执行文件中的每一条命令 {
while(getline(fileIn,cmdLine)) {
try { controller.runCommand(cmdLine); }catch(exception&e) { cout<<"Badlinein"<<FILE_NAME<<":"<<cmdLine<<endl; cout<<"Error:"<<e.what()<<endl; return1; } } fileIn.close(); //关闭文件
} 综合实例——对个人银行账户管理程序的改进
ofstreamfileOut(FILE_NAME,ios_base::app); //以追加模式
cout<<"(a)addaccount(d)deposit(w)withdraw(s)show(c)changeday(n)nextmonth(q)query(e)exit"<<endl; while(!controller.isEnd())//从标准输入读入命令并执行,直到退出 {
cout<<controller.getDate()<<"\tTotal:"<<Account::getTotal() <<"\tcommand>"; stringcmdLine; getline(cin,cmdLine);
try { if(controller.runCommand(cmdLine)) fileOut<<cmdLine<<endl; //将命令写入文件
}catch(AccountException&e) { cout<<"Error(#"<<e.getAccount()->getId()<<"):" <<e.what()<<endl; }catch(exception&e) { cout<<"Error:"<<e.what()<<endl; } } return0;}综合实例——对个人银行账户管理程序的改进运行结果如下:......(前面的输入和输出与之前给出的完全相同,篇幅所限,不再重复)2009-1-1Total:20482.9command>w220000buyacarError(#C5392394):notenoughcredit2009-1-1Total:20482.9command>w21500buyatelevision2009-1-1#C5392394-1500-1550buyatelevision2009-1-1Total:18982.9command>q2008-12-52009-1-32Error:Invaliddate2009-1-1Total:18982.9command>q2008-12-52009-1-312008-12-5#S3755217550010500salary2009-1-1#S375521717.7710517.8interest2009-1-1#0234234215.1610015.2interest2009-1-1#C5392394-50-50annualfee2009-1-1#C5392394-1500-1550buyatelevision2009-1-1Total:18982.9command>e异常处理异常处理标准程序库异常处理综合实例异常安全性原则智能指针异常安全性问题异常安全性原则一个异常安全的函数,在有异常抛出时:不应泄露任何资源不能使任何对象进入非法状态反例:第6讲中的下列代码:template<classT,intSIZE>voidStack<T,SIZE>::push(constT&item){ assert(!isFull()); //如果栈满了,则报错
list[++top]=item; //将新元素压入栈顶}如果赋值过程中有异常抛出,由于top已经增1,栈顶的内容将变得不确定异常安全性问题异常安全性原则该函数的修正版本:template<classT,intSIZE>voidStack<T,SIZE>::push(constT&item){ assert(!isFull()); //如果栈满了,则报错
list[top+1]=item;//将新元素压入栈顶
top++;}即使赋值时抛出异常,由于此时top并没有真正增1,因此当前对象的状态没有改变,该函数是异常安全的编写异常安全程序的原则异常安全性原则明确哪些操作绝对不会抛掷异常这些操作是异常安全编程的基石例:基本数据类型的绝大部分操作,指针的赋值、算术运算和比较运算,STL容器的swap函数尽量确保析构函数不抛掷异常编写异常安全程序的原则
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 圆管选购合同模板
- 大客户采购合同撰写指南
- 2024年度车辆买卖合同过户手续办理
- 酒水购销合同协议书
- 2024年度软件许可合同:大数据分析软件使用权
- 2024年度影视制作与发行合同:某电影项目的全流程合作
- 2024年升降式老练生产线项目可行性研究报告
- 2024年度腻子产品生产线技术升级合同:腻子生产商与技术供应商之间的技术升级协议
- 2024年中国解冻液市场调查研究报告
- 2024年中国化纤编织袋市场调查研究报告
- JGJ162-2008-建筑施工模板安全技术规范
- 2024年山西省文化旅游投资控股集团限公司校园招聘120人高频难、易错点500题模拟试题附带答案详解
- 2024年新北师大版数学一年级上册 第4单元 10以内数加与减 第9课时 可爱的企鹅 教学课件
- 2024年中国敞篷车市场调查研究报告
- 江西九江富和建设投资集团有限公司招聘笔试题库2024
- 光伏消防演练方案及流程
- TCISA 415-2024 高炉本体数字孪生系统技术要求
- 医美代运营合作协议书范本
- 中学英语词汇教学
- 2024年重庆市高考思想政治试卷真题(含答案解析)
- 溃疡性结肠炎护理查房 2
评论
0/150
提交评论