异常处理
C++Builder支持C++异常处理、基于C的结构异常处理以及VCL异常处理。
注意 本章中所用的关于C++异常处理及结构异常处理的例子通过命令行使用bcc32.exe可成功地编译并运行,而不是使用IDE。在调用标准C++例程及对象时可用C++异常处理。
VCL异常处理可在IDE内进行。实际上,尽管C++Builder支持C++异常处理和基于C的结构异常处理。但使用C++Builder和VCL可开发包含内嵌异常处理的例程的应用程序,这些例程可以在出现错误时自动发送异常。
8.1 C++异常处理
异常是指需要特殊处理的例外情况,包括运行时发生的错误,如除数为零,存储空间不足等。异常处理提供了一种标准的方法以处理错误,发现可预知及不可预知的问题,及允许开发者识别、查出和修改错漏之处(bugs)。
8.1.1异常处理的ANSI规定
C++Builder异常处理支持ANSI/ISO提议的C++工作标准。发送异常可允许你收集发送点的信息,这将有助于诊断异常发生的原因。可使用异常处理程序来确定程序终止之前的操作。只有同步异常(错误都由程序内部引起)可被处理。外部事件(例如按下Ctrl+C组合键)不被认为是一个异常。
C++语言规定所有的异常都应在一个try-block中被发送。这个块之后紧接着是一个或多个catch块,用于识别和处理try-block中发生的错误。
8.1.2异常处理语法
异常处理要求使用三个关键字:try、catch及throw。程序通过可能产生特殊状况的trying语句以准备捕捉异常。当C++程序发送一个异常时,可将控制转移或throw到程序另外的被称为异常处理程序的、用于处理该类异常的部分中去。这种处理程序被称为catch异常。程序通过执行throw语句来发送异常。throw语句通常在一个函数内发生。
throw "overflow";
在这个例子中,语句发送一个描述异常类型的对象,在这里,是一个算术运算溢出。从而程序的另一部分可捕捉并处理这个异常对象。要使用异常处理,需将代码封闭在一个try/catch结构中.
注意 C程序中不支持try、catch及throw关键字。
一个由try确定的try-block后必须紧接着一个由catch确定的处理程序。try-block是一段用于确定程序执行时的控制流的语句。若一个异常在try-block中被发送,程序控制被转移到适当的异常处理程序。 处理程序是一段被设计来用于处理异常的代码。C++语言要求至少有一个处理程序紧接着try-block。
程序应包括一个可处理程序中可能发生的各个异常的处理程序。注意C程序中不支持try、catch及throw关键字。一个由try确定的try-block后必须紧接着一个由catch确定的处理程序。try-block是一段用于确定程序执行时的控制流的语句。若一个异常在try-block中被发送,程序控制被转移到适当的异常处理程序。处理程序是一段被设计来用于处理异常的代码。C++语言要求至少有一个处理程序紧接着try-block。程序应包括一个可处理程序中可能发生的各个异常的处理程序。
8.1.3声明异常
虽然C++允许异常可为任意类型,但异常对象还是很有用的。异常对象可当作其他对象一样看待。异常对象将异常发送点的信息携带到异常对象被捕捉的地方。应用程序的用户在程序运行时遇到不正常的情况时会很需要这些信息。由C++语言预定义的异常,在联机帮助中的“LibraryReference”中介绍。
8.1.4发送异常
可能发生异常的代码块需以try为前缀同时封闭在花括号内。这表明程序准备检查异常。若异常发生,则程序流中断,然后会发生:
· 程序搜索匹配的处理程序。
· 若找到处理程序,则栈在该点被打开。
· 程序控制转到处理程序。
· 若没有找到处理程序,可调用set_terminate()以提供终止处理程序,否则,程序会调用terminate函数。
若无异常被发送,程序正常执行。
当异常发生时,throw语句初始化一个T类型(匹配arg参数的类型)的临时对象在throw(Targ)中使用。对象的其他拷贝可在编译器需要时生成。因此,对于包含子对象的类来说,定义一个拷贝结构很有用(对于按位拷贝无须定义拷贝结构)。
示例
下列例子说明了几种发送异常的方法。
注意这些例子通过命令行使用bcc32.exe可成功地编译并运行,而不需使用IDE。
例1:下例传递一个Out对象给处理程序。
例2:下例只是将上例中的异常重新发送。
下例在没有处理程序存在是调用terminate
例3:下例指定了festival和test可发送的异常列表。其他异常不能从festival中被传递出去。
若festival产生了一个Out之外的异常,它被看作一个意外的异常,程序控制会转到例4中所示的unexpected函数。
例4:下例说明test不应发送任何异常。若test中的任何函数(例如操作符new)发送了一个异常,它应在test内被捕捉和处理。否则,这个异常就是test规定之外的异常。可调用set_unexpected()设置另外一个处理程序。否则,unexpected函数将被调用。
当异常发生时,throw语句初始化一个T类型(匹配arg参数的类型)的临时对象在throw(Targ)中使用。对象的其他拷贝可在编译器需要时生成。因此,对于定义一个如下所示的异常对象的拷贝结构很有用。