03异常(Exceptions)异常

C++增加了 exceptions 性质后,深远而根本地、并可能令人不舒服地改变了许多事情。例如,原始指针的使用如今竟成为一种高风险行为,资源泄漏(resource leaks)的机会大增,撰写符合期望的 constructors和 destructors的难度也大增。程序员必须特别小心,防止程序在执行时突然中止。可执行文件和程序库变得更大、速度更慢。

上述所言都只是我们知道的事情而已。欲将 exceptions 纳入程序设计考虑,还有许多 C++社区所不清楚的相关事务,其中最大的部分就是不知如何正确掌握它。至今尚未有某种技术被大家公认,一旦常态性地施行后,便能够引导软件行为在“exceptions 被抛出”时可预期并且稳定。(如果想深入这些主题,请参考本书p287所推荐的 Tom Cargill 文章。如果想知道这些主题的最新突破,请看 Jack Reeves发表于 C++Report,1996/03 的文章,以及 Herb Sutter发表于C++Report,1997/09,11,12的文章。)

我们都很清楚一点:程序之所以在 exceptions 出现时仍有良好行为,不是因为碰巧如此,而是因为它们加入了 exceptions 的考虑。“面对 exception 依然安全(所谓 exception-safe)”的程序并非是意外诞生的。一个程序如果没有针对exceptions 特别做设计,却要求它在 exceptions 出现时有良好的行为,那就好像未针对多线程(multiple threads)做设计,却希望多线程发生时能够有良好表现一样:痴人说梦!

回过头来说,为什么使用 exceptions?自从 C 发明以来,C 程序员用来避免错误的程序技术已经够多的了,为什么要再招惹 exceptions?尤其如果它们像我说的那样带来一大堆问题的话?答案很简单:exceptions 无法被忽略。如果一个函数利用“设定状态变量”的方式或是利用“返回错误码”的方式发出一个异常信号,无法保证此函数的调用者会检查那个变量或检验那个错误码。于是程序的执行可能会一直继续下去,远离错误发生地点。但是如果函数以抛出 exception 的方式发出异常信号,而该 exception 未被捕捉,程序的执行便会立刻中止。

C 程序员唯有以 setjmp 和 longjmp 才能近似这样的行为。但是 longjmp在 C++中有一个严重缺陷:当它调整栈(stack)的时候,无法调用局部(local)对象的destructors。大部分 C++程序很依赖这些 destructors 被调用,所以 setjmp和longjmp 对真正的 exceptions 而言不是个良好的替代品。如果你需要一个“绝对不会被忽略的”异常信号发射方法,而且发射后的 stack处理过程又能够确保局部对象的 destructors 被调用,那么你需要 C++exceptions。它是最简单的方法了。

关于如何撰写 exceptions-safe 程序,我们有很多需要学习。以下所列条款只能架构出一个不很完全的“exception-safe 软件”设计指南。尽管如此,它们介绍了在C++中使用 exceptions 时的许多重要考虑。只要留意以下指引,你就可以改善软件的正确性、稳健性、效率,而且你可以避开许多因 exceptions 而产生的问题。

条款 9:利用 destructors避免泄漏资源

对指针说拜拜。承认吧,你从未真正喜欢过它,对不?

好,你不需要对所有指针说拜拜,但是你真的得对那些用来操控局部性资源(local resources)的指针说莎唷娜拉了。举个例子,你正在为“小动物收养保护中心”(一个专门为小狗小猫寻找收养家庭的组织)编写一个软件。收养中心每天都会产生一个文件,其中有它所安排的当天收养个案。你的工作就是写一个程序,读这些文件,然后为每一个收养个案做适当处理。

合理的想法是定义一个抽象基类(abstract base class) ALA ("Adorable Little Animal"),再从中派生出针对小狗和小猫的具体类(concrete classes)。其中有个虚函数 processAdoption,负责“因动物种类而异”的必要处理动作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值