打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
再看C 异常安全性 - txj_killer的开发学习日志

再看C++异常安全性

星期一, 八月 8. 2005
    在最开始,我把C++异常机制错误地理解为返回错误值的代替品,认为如果采纳异常机制,总是应该写出异常抛出和处理代码,因此保证异常安全变成一件繁琐的事,而且极其低效。这个认识显然是错误的。
    在《ExceptionalC++》中提到的异常安全性,是以状态一致性和异常中立性为基础的,在这种情况下,我们写的代码要保证异常安全,需要注意的就是优先满足内聚性,并且注意提交或回退语义,这也就是我上一篇笔记的主题。这样确实能提供很大程度上的异常安全性,可是,我们也应该注意到,这里的所有讨论都是有很强针对性的,并不是放之四海而皆准,要真正在C++开发中满足异常安全,我们要注意的事还有很多。
    首先,我们必须考虑C++异常机制出现的理由。对于传统的C语言而言,它是完全面向过程的,用其写出的程序在设计合理的情况下可以实现相当程度的模块化,模块之间我们面对的就只有函数接口而已,根据程序流程,处理每一步返回的错误就基本可以满足要求了(当然面向过程也可能会对错误传递有比较高的要求,比如windows下的SEH机制就是可以在面向过程范性中使用的异常机制)。而C++不同,C++的模块化机制是非常弱的(甚至可以说C++不支持模块化)——当然是指基于对象和面向对象开发范性而言。这样我们在进行代码发布的时候,客户端面对的并不是一个函数接口的剖面,而是一个以类和类的对象为基础构成的一个抽象描述剖面。特别在一个大型程序中,即使经过精心的设计,类与类之间,对象与对象之间的关系都是极其错综复杂的。这样,一个对象内部发生错误,对这个错误感兴趣的可能不只直接调用引发该错误的成员函数的那个部分,而需要某种机制将这种错误消息传递给其它单独开发的部分。正是这种要求促成了C++异常机制的产生(当然还有其它因素,比如对错误集中处理的要求,但因为效率的要求,这些因素在实际应用中仿佛考虑得比较少,毕竟C++和Java是针对不同用途的语言)。这里不得不提到COM的错误传递,COM是完全模块化的,我们面对的仅仅是接口而已,所以我们可以看出IDL产生的C++代码都是使用返回值来进行错误传递的。但是一个例外就是对应的Java代码,却是将返回的HRESULT转换为异常处理的,这也能看出C++和Java对异常机制的不同态度。
    另一方面,我们必须看到异常机制的低效性和其副作用。由于大量的运行时支持,异常机制的效率是非常低的,至少是要比普通函数调用还要低很多,所以C++大师都建议我们不到必要时不要使用异常。而且由于异常在传递过程中的栈展开语义,造成了不可恢复性的破坏,对于需要长时间运行的程序而言这是不允许的,它们要求把错误局限在一个局部处理掉。
    正是基于以上考虑,我们在代码中使用异常机制的时候并不能完全象《ExceptionalC++》中说的那样去遵守异常中立性。E书是针对库接口开发而言的,库除了必须尽量满足可重用性,还必须满足可扩展性和灵活性,在这种情况下,在代码中改变应有的异常传递是不明智的,这时必须给客户最大的选择权利,让客户端决定异常应该怎么被处理。而我们进行开发时则不一定了,我们提供的类接口也许为了让客户端专注于问题处理,而申明了异常规范(exceptionspecification),将接口内部可能产生的其它异常捕获并处理掉。另外上面提到的需要程序长时间运行的情况也要求把异常局限起来处理掉并继续代码的执行。
    至于我们的代码究竟该使用异常还是使用返回值报告错误,就完全视乎该错误应该被哪些部分知道而定了。如果只是需要在我们可以掌控的范围内传递该错误消息,那么就应该尽量使用返回值报告错误而不是异常,反之,则只有使用异常机制了。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
编程注意(待完备)
工作中关于合作的三个层次的思考
浅谈代码分层:构建模块化程序
如何减小ABAP业务代码的复杂度
0基础学习C 语言:你使用函数必须知道的3点注意事项
Go语言和Python哪一个更容易学呢?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服