欢迎来到天天文库
浏览记录
ID:34448303
大小:722.72 KB
页数:23页
时间:2019-03-06
《c++编程思想17》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、下载下载第17章异常处理错误修复技术的改进是提高代码健壮性的最有效方法之一。但是,大多数程序设计人员在实际设计中往往忽略出错处理,似乎是在没有错误的状态下编程。毫无疑问,出错处理的繁琐及错误检查引起的代码膨胀是导致上述问题的主要原因。例如,虽然printf()函数可返回打印参数的个数,但是实际程序设计中没有人检查该值。出错处理引起的代码膨胀将不可避免地增加程序阅读的困难,这对于程序设计人员来说是十分令人烦恼的。C语言中实现出错处理的方法是将用户函数与出错处理程序紧密地结合起来,但是这将造成出错处理使用的不方便和难以接受。异常处理是C++语言的一个主要特征,它提出了出错处理更加完
2、美的方法。1)出错处理程序的编写不再繁琐,也不须将出错处理程序与“通常”代码紧密结合。在错误有可能出现处写一些代码,并在后面的单独节中加入出错处理程序。如果程序中多次调用一个函数,在程序中加入一个函数出错处理程序即可。2)错误发生是不会被忽略的。如果被调用函数需发送一条出错信息给调用函数,它可向调用函数发送一描述出错信息的对象。如果调用函数没有捕捉和处理该错误信号,在后续时刻该调用函数将继续发送描述该出错信息的对象,直到该出错信息被捕捉和处理。在这一章中我们将讨论C语言的出错处理方法,讨论为何该方法在C语言中不是很理想的,并且无法在C++中使用;然后学习try,throw和ca
3、tch的用法,它们在C++中支持异常处理。17.1C语言的出错处理本书在第8章以前使用C标准库的assert()宏作为出错处理的方法。第8章以后assert()被按照原先的设计目的使用:在开发过程中,使用它们,完成后用#defineNDEBUG使之失效,以便推出产品。为了在运行时检查错误,assert()被allege()函数和第8章中引入的宏所取代。通常我们会说:“对于出错处理我们必须面对复杂的代码,但是在这个例子中我们不必由此感到烦恼”。allege()函数对一些小型程序很方便,对于复杂的大型程序,所编写的出错处理程序也将更加复杂。在通过检查条件我们能确切地知道做什么的情况
4、下,出错处理就变得十分明确和容易了,因为我们通过上下文得到了所有必要的信息。当然,我们只是在这一点上处理错误。这些都是十分普通的错误,不是这一章的主题。若错误问题发生时在一定的上下文环境中得不到足够的信息,则需要从更大的上下文环境中提取出错处理信息,下面给出了C语言处理这类情况的三种典型方法。1)出错信息可通过函数的返回值获得。如果函数返回值不能用,则可设置一全局错误判断标志(标准C语言中errno()和perror()函数支持这一方法)。正如前文提到的,由于对每个函数调用都进行错误检查,这十分繁琐并增加了程序的混乱度。程序设计者可能简单地忽略这些出错信息,因为乏味而迷乱的错误
5、检查必须随着每个函数调用而出现。另外,来自偶然出现异常的函数的返回值可能并不反映什么问题。第17章异常处理361下载2)可使用C标准库中一般不太熟悉的信号处理系统,利用signal()函数(判断事件发生的类型)和raise()函数(产生事件)。由于信号产生库的使用者必须理解和安装合适的信号处理系统,所以应紧密结合各信号产生库,但对于大型项目,不同库之间的信号可能会产生冲突。3)使用C标准库中非局部的跳转函数:setjmp()和longjmp()。setjmp()函数可在程序中存储一典型的正常状态,如果进入错误状态,longjmp()可恢复setjmp()函数的设定状态,并且状态
6、被恢复时的存储地点与错误的发生地点紧密联系。考虑C++语言的出错处理方案时会存在另一个关键性问题:由于C语言的信号处理技术和setjmp/longjmp函数不能调用析构函数,所以对象不能被正确地清除。由于对象不能被清除,它将被保留下来并且将不能再次被存取,所以存在这种问题时实际上是不可能有效正确地从异常情况中恢复出来。下面的例子将演示setjmp/longjmp的这一特点:setjmp()是一个特别的函数,因为如果我们直接调用它,它就把当前进程状态的所有相关信息存放在jmp_buf中,并返回零。这样,它的行为象通常的函数。然而,如果使用同一个jmp_buf调用longjmp()
7、,这就象再次从setjmp()返回,即正确地弹出setjmp()的后端。这时,返回值对于longjmp()是第二个参数,所以能发现实际上从longjmp()中返回了。可以想象,有多个362C++编程思想下载不同的jmp_buf,可以弹出程序的多个不同位置的信息。局部goto(用标号)和这个非局部跳转的不同在于我们能通过setjmp/longjmp跳转到任何地方(一些限制不在这里讨论)。在C++中的问题是,longjmp()不适用于对象,特别是,当它跳出范围时它不调用析构函数[1]。析构函数调
此文档下载收益归作者所有