exit()和abort()不销毁对象
对象可以持有从构造函数或者某个成员函数中获得的资源:从free store中分配的内存,文件句柄,通信端口,I/O设备等等。这些资源必须在适当时候被释放。通常,资源都是由析构函数来释放。这种设计方法被称为resource initialization is acquisition。在栈上建立的局部对象会自动销毁。然而abort() 和exit()并不调用这些局部对象的析构函数。因此,程序的意外终止将会引起无法挽回的损害:数据库被破坏,文件可能丢失,并且一些有价值的数据可能丢失。基于这个原因,请不要在面向对象环境中使用abort()和exit()。
进入异常处理
正如你所见,传统C的错误处理方法并不适合C++,C++的一个设计目标就是让用C++进行大规模软件开发比C更好更安全。
C++的设计者们已经意识到缺乏合适的错误处理机制使得实现这一目标相当的困难。他们试图寻找一种完全摆脱C的错误处理缺陷的解决方案。其中的一种想法就是建立在当异常被触发的时候程序自动把控制权传递给系统。机制必须简单,并且它能够使程序员从不断的检查一个全局标记或者返回值的苦差事中解脱出来。另外,它还必须保证异常处理程序能够自动获得异常信息。最终它还要确保当一个异常没有在本地处理的时候,本地对象能够被适当的销毁,并且把它所持有的资源释放。
1989年,在多年的研究和多方建议下,异常处理进入C++。C++并不是第一个对结构化运行期错误处理进行支持的语言。早在20世纪60年代,PL/1就提供了一种内建的异常处理机制;Ada也在20世纪80年代提供了自己的异常处理,另外还有几种语言也做到了这一点。但是这些异常处理模型没有一个适合C++对象模型和程序结构。因此,被提议的C++异常处理是独一无二的,并且它已经作为了一种模型出现在一些新产生的语言之中。
异常处理机制的实现被证明是一种挑战。第一个C++编译器,cfront,在UNIX环境下运行。和许多UNIX编译器一样,它首先是作为一个翻译器把C++代码转换成C,接着再编译C代码。Cfront 4.0计划引入异常处理,然而,异常处理机制的实现是如此的复杂,以至于cfront 4.0的开发团队在用了一年时间设计它之后完全的放弃了这个项目。Cfront 4.0再也没有出台。然而,异常处理却成为了标准C++的有机组成部分。后来出现的一些编译器都支持了它。在接下来的部分里将会解释为什么在cfront以及任何编译器下实现异常处理是如此的困难。 实现异常处理所面临的挑战