[转] C++ try catch() throw 异常处理
|
其它很多程序员一样,本书的主人公阿愚也是在初学C++时,在C++的sample代码中与异常处理的编程方法初次邂逅的,如下: try // Other normal program statements 瞧瞧,代码看上去显得那么整齐、干净,try block和catch block遥相呼应,多有对称美呀!因此主人公初次见面后就一见钟情了。 为什么要选用异常处理的编程方法? void main(int argc, char* argv[]) } 因为程序的执行过程中总会遇到许多可预知或不可预知的错误事件,例如说,由于内存资源有限导致需要分配的内存失败了;或某个目录下本应存在的一个文件 但C++中的异常处理的机制彻底改变了这种面貌,它使真正的计算处理和错误处理分开来,让程序员不再被这些琐碎的事情所烦扰,能关注于真正的计算处理工作。同时代码的可读性也好了。因此我们有理由选择异常处理的编程方法。具体原因如下: 相信绝大多数程序员都知道C++中的异常处理的编程方法,可还是有很多人已习惯原来单纯的面向过程的代码组织方式,不太习惯或较少使用 如果您喜欢玩一款游戏,您必须先要很好理解这款游戏的规则。同样主人公阿愚喜欢上C++中异常处理后,当然也首先关注它的游戏规则,这就是C++中异常处理的语法。
关键字 1、 try 语法 1、还是给一个例子吧!如下: int main() //定义一个try block,它是用一对花括号{}所括起来的块作用域的代码块 //这里抛出一个异常(其中异常对象的数据类型是int,值为1) cout << "在 try block 中, 由于前面抛出了一个异常,因此这里的代码是不会得以执行到的" << endl; cout << "Back in main. Execution resumes here." << endl; } 2、语法很简单吧!的确如此。另外一个try block可以有多个对应的catch block,可为什么要多个catch block呢?这是因 int main() cout << "在 try block 中, 准备抛出一个double数据类型的异常." << endl; return 0; 3、一个函数中可以有多个trycatch结构块,例子如下: int main() //这里是二个trycatch结构块,当然也可以有第三、第四个,甚至更多 return 0; 4、
上面提到一个try block可以有多个对应的catch block,这样便于不同的异常错误分类处理,其实这只是异常错误分类处理的方法之一(暂且 把它叫做横向展开的吧!)。另外还有一种就是纵向的,也即是分层的、trycatch块是可以嵌套的,当在低层的trycatch结构块中不能匹配到相同 类型的catch block时,它就会到上层的trycatch块中去寻找匹配到正确的catch block异常处理模块。例程如下: int main() cout << "在 try block 中, 准备抛出一个double数据类型的异常." << endl; return 0; 5、讲到是trycatch块是可以嵌套分层的,并且通过异常对象的数据类型来进行匹配,以找到正确的catch block异常错误处理代码。这里就不得不详细叙述一下通过异常对象的数据类型来进行匹配找到正确的catch block的过程。 (1) 首先在抛出异常的trycatch块中查找catch block,按顺序先是与第一个catch block块匹配,如果抛出的异常对象的 (2) 如果有二个或更多的catch block,则继续查找匹配第二个、第三个,乃至最后一个catch block,如匹配成功,则进入到对应的catch block中执行;否则到三步; (3) 返回到上一级的trycatch块中,按规则继续查找对应的catch block。如果找到,进入到对应的catch block中执行;否则到四步; (4) 再到上上级的trycatch块中,如此不断递归,直到匹配到顶级的trycatch块中的最后一个catch block,如果找到,进入到对应的catch block中执行;否则程序将会执行terminate()退出。 另外分层嵌套的trycatch块是可以跨越函数作用域的,例程如下: void Func() throw() int main() cout << "在 try block 中, 准备抛出一个double数据类型的异常." << endl; throw 0.5;
} catch( double& d_value ) { cout << "在 catch block 中, double数据类型处理异常错误。”<< endl; } catch( int& value ) { //这个例子中,Func()函数中抛出的异常会在此被处理 cout << "在 catch block 中, int数据类型处理异常错误。”<< endl; } return 0; 6、刚才提到,嵌套的trycatch块是可以跨越函数作用域的,其实这里面还有另外一层涵义,就是抛出异常对象的函数中并不一定必须存在 void Func() throw() int main() cout << "在 try block 中, 准备抛出一个double数据类型的异常." << endl; //如果这里调用这个函数,那么由于main()已经是调用栈的顶层函数,因此不能找 ///////////////////////////////////////////////////
为什么要用catch(…)这个东东?
程序员朋友们也许会说,这还有问吗?这篇文章的一开始不就讲到了吗?catch(…)能够捕获多种数据类型的异常对象,所以它提供给程序员一种对异常 void Func() 还有,特别是VC程序员为了使开发的系统有更好的可靠性,往往在应用程序的入口函数中(如MFC框架的开发环境下 BOOL CXXXApp::InitInstance() AfxEnableControlContainer(); // Standard initialization #ifdef _AFXDLL // 注意这里有一个顶层的trycatch块,并且使用catch(…)来捕获一切所有的异常 // Since the dialog has been closed, return FALSE so that we exit the 通过上面的例程和分析可以得出,由于catch(…)能够捕获所有数据类型的异常对象,所以在恰当的地方使用catch(…)确实可以使软件系统有着 从上面的异常分类来看,它有明显的层次性和继承性,这恰恰和面向对象的继承思想如出一辙,因此用对象来描述程序中出现的异常是再恰当不过的了。而且可以利用面向对象的特性很好的对异常进行分类处理,例如有这样一个例子:
void OpenFile(string f) void ReadFile(File f) void WriteFile(File f) void Func() ReadFile(…); WriteFile(…); 通过上面简单的例子可以看出,利用面向对象的方法,确实能很好地对异常进行分类处理,分层处理,如果异常能得以恢复的尽可能去实现恢复,否则向上层重 现在回想一下上一篇文章中提出的那个问题?就是既然有其它很好的方法(利用类的继承性)来可以代替catch(…)提供的异常集中处理,那为什么 异常处理中采用面向对象技术还有哪些好处呢? 上面讲到,用对象来描述程序中出现的异常除了能很好地分层处理异常外,还有那些好处呢?当然除了好处大大的外,好处也是多多的,例如: (1) 面向对象的实现中,一般都很好的实现了对象的RTTI技术,如果异常用对象来表示,那么就可以很好完成异常对象的数据类型匹配,还有就是函数 (2) 面向对象的实现中,一般都很好的实现了对象的构造、对象的销毁、对象的转存复制等等,所以这也为异常处理模型中,异常对象的转存复制和对象销毁提供了很好的支持,容易控制; 在异常处理的分层管理下,异常对象的重新抛出往往非常常见,本文中刚才的例子就有这样的情况,但当时仅一笔带过而已,为了表明对它的重视,下一篇文章重点讨论一下异常对象的rethrow处理。 |
[转] C++ try catch() throw 异常处理的更多相关文章
- 异常处理(try catch throw)详解(C++)
选择异常处理的编程方法的具体原因如下: 1.把错误处理和真正的工作分开来: 2.代码更易组织,更清晰,复杂的工作任务更容易实现: 3.毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了: 4 ...
- Ruby跳出多层循环 catch...throw
在编码的时候,有时候会遇到嵌套循环的情况,最内部的循环结束的时候,想跳出所有循环,这个时候我们往往采用通过内部循环设置一个flag来控制外部跳出循环条件,比如: #encoding:utf-8 for ...
- (六)JavaScript之[Regular Expression]与[错误(try, catch, throw)]
10].正则表达式 /** * 正则表达式(Regular Expression): * * 用于文本搜索和文本替换 * */ /** * /good/i是一个正则表达式. * good是一个模式(用 ...
- js学习笔记2:循环和try/catch/throw
今天学习了js的比较.if/else.switch/case和各种循环,这些东西每种语言都大同小异,没什么好看的,重点说一下js的循环. JavaScript 支持不同类型的循环: for - 循环代 ...
- C++异常处理:try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- C++异常处理: try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- C++ 异常处理(try catch throw)、命名空间
一.c++工具 模板(函数模板.类模板).异常处理.命名空间等功能是c++编译器的功能,语言本身不自带,这些功能已经成为ANSI C++标准了,建议所有的编译器都带这些功能,早期的c++是没有这些功能 ...
- 22 C#中的异常处理入门 try catch throw
软件运行过程中,如果出现了软件正常运行不应该出现的情况,软件就出现了异常.这时候我们需要去处理这些异常.或者让程序终止,避免出现更严重的错误.或者提示用户进行某些更改让程序可以继续运行下去. C#编程 ...
- C++异常处理(try catch throw)完全攻略
程序运行时常会碰到一些异常情况,例如: 做除法的时候除数为 0: 用户输入年龄时输入了一个负数: 用 new 运算符动态分配空间时,空间不够导致无法分配: 访问数组元素时,下标越界:打开文件读取时,文 ...
随机推荐
- szoj461【四校联考0430】挑战
传送门:(涉及版权忽略) [题解] 我们发现n的范围很小,提示我们可以折半,然后我们就会了O(T2^(n/2)*n)的做法,然而会T. 考虑如何优化.直接排序会多一个log(2^(n/2))也就是n, ...
- [转载]解决clickonce不支持administer权限问题
转自ClickOnce deployment vs. requestedExecutionLevel = requireAdministrator ClickOnce方式部署应用简单方便,估计很多人都 ...
- SQLSERVER数据库置疑、可疑、脱机、单用户、紧急模式等的修复
数据库出现置疑.可疑.脱机.单用户.紧急模式主要是因为数据库的日志文件除了问题,2000和2008修复方式不一样,2008的修复脚本在2000中不适用,主要是不被2000识别. 假设数据库名为:eis ...
- javascript的阻塞机制
javascript的阻塞机制 浏览器在执行javascript代码时,不能同时做其它事情,当遇到javascript时,浏览器会下载js文件,解析并执行该文件,而在这期间页面的渲染是完全被阻塞的,因 ...
- LCD实验学习笔记(二):head.S
ARM加电后从0地址开始取指执行. 连接为bin文件时时,连接脚本lcd.lds指定将head.o放在开头,所以head.S就是系统起步的地方. head.S开头就是异常向量定义,0地址就是reset ...
- Anaconda 2和3在Win10上共存
1. 安装Anaconda 2和3 Anaconda 2中的python2为主,Anaconda 3中的python3为辅.先装Anaconda 2,并在安装时选择注册为系统python,再装Anac ...
- 使用Mybatis做批量插入
最近有个需求,将excel的数据导入的数据库的这个一个操作. 工作主要分为:解析excel,将excel中的数据单条循环插入数据库. 使用框架:mybatis+spring 使用过Mybatis的人都 ...
- redis使用管道pipeline提升批量操作性能(php演示)
Redis是一个TCP服务器,支持请求/响应协议. 在Redis中,请求通过以下步骤完成: 客户端向服务器发送查询,并从套接字读取,通常以阻塞的方式,用于服务器响应. 服务器处理命令并将响应发送回客户 ...
- ThreadLocal深度解析
本文基于jdk1.8.0_66写成 0. ThreadLocal简介 ThreadLocal可以提供线程内的局部对象,合理的使用可以避免线程冲突的问题比方说SimpleDateFormat是线程不安全 ...
- linux中Firefox浏览器 手动安装 flash
打开firefox浏览器,当你打开有关音频或者视频的网站时候,会提示你安装 flash,可是,官网提示,需要手动安装. 1.先从提示的官网上下载好文件 “install_flash_player_11 ...