BCB讲座第十三讲异常处理
编程中的错误处理:异常管理与容错机制
编程中的错误处理:异常管理与容错机制在编程的世界里,错误处理就像是为程序保驾护航的卫士,确保程序在面对各种意外情况时能够稳健运行。
其中,异常管理和容错机制是两个至关重要的方面,它们共同为构建可靠、健壮的程序奠定了基础。
首先,让我们来理解一下什么是异常。
简单来说,异常就是程序运行时出现的不正常情况,比如除以零、访问不存在的数组元素、文件无法打开等。
当这些异常情况发生时,如果没有妥善处理,程序可能会崩溃或者产生不可预测的结果。
异常管理是一种机制,用于在程序中捕获和处理这些异常情况。
在许多编程语言中,都提供了专门的语法和结构来实现异常管理。
例如,在 Java 中,使用`trycatch`语句块来捕获异常。
`try`块中包含可能会抛出异常的代码,而`catch`块则用于处理相应类型的异常。
通过异常管理,我们可以让程序在出现异常时采取适当的措施,而不是直接崩溃。
比如,当文件无法打开时,我们可以提示用户文件不存在,并提供重新选择文件的机会;当网络连接中断时,我们可以尝试重新连接或者提示用户网络出现问题。
然而,仅仅捕获异常还不够,我们还需要对异常进行合理的分类和处理。
不同类型的异常可能需要不同的处理方式。
比如,对于可恢复的异常,我们可以尝试采取一些措施来恢复正常状态;对于不可恢复的异常,可能需要终止程序并给出明确的错误提示。
容错机制则是一种更广泛的概念,它不仅仅包括对异常的处理,还包括在程序设计阶段就考虑到可能出现的错误情况,并采取相应的预防措施。
比如说,在设计一个网络应用程序时,我们可以考虑到网络延迟或者丢包的情况,通过设置合适的超时时间和重试机制来提高程序的容错能力。
在处理数据时,我们可以对输入的数据进行有效性验证,避免因无效数据导致的错误。
在实现容错机制时,需要权衡容错的成本和收益。
过度的容错可能会导致程序变得复杂、效率低下,而容错不足则可能导致程序在面对常见的错误情况时表现不佳。
另外,日志记录也是错误处理中非常重要的一部分。
第12章异常处理
第12章异常处理异常处理是程序设计中必不可少的一部分,它可以帮助我们捕获并处理代码中发生的异常情况,使程序更加健壮和可靠。
在本章中,我们将学习异常处理的概念、语法和使用方法。
异常是指在程序执行期间发生的意外或异常情况,它可能导致程序的正常执行流程中断或产生错误的输出。
例如,一个数字除以零、读取一个不存在的文件或访问一个不存在的数组索引都属于异常情况。
在Java中,异常是通过异常类的实例来表示的。
每个异常类都有一个特定的异常类型,用来指示异常的种类。
在Java中,所有的异常都是从Throwable类派生而来的。
Throwable类有两个直接子类:Error和Exception,其中Error表示严重的程序错误,一般无法修复,而Exception则表示可被捕获和处理的异常。
Java的异常处理使用了try-catch语句块来捕获和处理异常。
try语句块用于包含可能出现异常的代码,catch语句块用于捕获并处理异常。
try-catch语句中可以有多个catch语句块,用于捕获不同类型的异常。
try-catch语句的基本语法如下:```try//可能出现异常的代码} catch (异常类型1 异常对象)//处理异常的代码} catch (异常类型2 异常对象)//处理异常的代码} finally//不管是否发生异常,总是会执行的代码```try语句块中是程序可能发生异常的代码,catch语句块用来捕获并处理异常。
多个catch语句块可以用来捕获不同类型的异常,当异常类型与一些catch语句块匹配时,该catch语句块将执行。
finally语句块中的代码总是会被执行,不管是否发生异常。
在catch语句块中,我们可以通过异常对象来获取异常的详细信息,例如异常的类型、消息和堆栈跟踪等。
我们可以根据需要进行适当的处理,比如输出错误信息、记录日志、重试操作或者终止程序的执行。
除了使用catch语句块来捕获异常,我们还可以使用throws语句来声明要抛出的异常。
如何进行编程中的错误处理和异常处理
如何进行编程中的错误处理和异常处理在进行编程时,错误处理和异常处理是非常重要的技能。
错误处理和异常处理的目的是在代码运行时检测和处理潜在的错误,以保持程序的稳定性和正确性。
本文将介绍如何进行编程中的错误处理和异常处理。
一、错误处理错误处理用于处理已知的错误情况,例如输入错误、操作错误等。
以下是一些常见的错误处理方法:1. 输入验证:在接受用户输入之前,进行输入验证以确保输入的数据符合要求。
例如,如果需要接受一个数字作为输入,就可以使用验证函数来检查输入是否为数字。
2. 异常捕获:在可能发生错误的代码块中使用try-catch语句来捕获异常。
当异常发生时,程序会跳转到catch块,给用户一个友好的错误提示并采取适当的措施。
3. 日志记录:在程序中使用日志记录来记录错误的发生。
可以使用内置的日志记录库或第三方库来记录错误信息,以便后续分析和修复错误。
4. 错误处理函数:编写一些通用的错误处理函数,用于处理特定类型的错误。
这些函数可以在发生错误时执行特定的操作,如显示错误消息、重试操作等。
二、异常处理异常处理用于处理未知的错误情况,例如运行时错误、系统错误等。
以下是一些常见的异常处理方法:1. 异常类型定义:定义自定义异常类型,以便在需要时抛出特定异常。
这些异常类型可以从内置的异常类型派生,并添加自定义的错误信息。
2. 异常抛出:在代码中使用throw语句来抛出异常。
当发生错误时,可以在代码中使用throw语句来抛出异常,并在调用该代码的位置使用try-catch语句来处理异常。
3. 异常处理器:编写一些异常处理器函数,用于捕获和处理特定类型的异常。
这些处理器函数可以在发生异常时执行特定的操作,如显示错误消息、重试操作等。
4. 异常链:在处理异常时,可以将多个异常链接在一起形成异常链。
这样可以更好地追踪异常的来源和处理过程。
三、错误处理和异常处理的最佳实践除了上述方法外,以下是一些错误处理和异常处理的最佳实践:1. 适当的错误信息:当发生错误时,应该提供清晰和明确的错误信息,以帮助用户理解错误原因并采取适当的措施。
异常处理原则详解
异常处理原则详解在软件开发和系统设计的领域中,异常处理是一个至关重要的环节。
它就像是为程序运行保驾护航的卫士,能够有效地应对各种意外情况,确保系统的稳定性和可靠性。
那么,什么是异常处理?异常处理又有哪些原则需要我们遵循呢?首先,我们要明白异常是指在程序运行过程中出现的不正常情况,例如除以零、数组越界、文件无法打开等。
而异常处理就是为了在这些异常情况发生时,能够采取适当的措施,避免程序崩溃或者产生错误的结果。
异常处理的第一个原则是“早发现,早处理”。
这意味着在程序中,我们应该尽可能在异常发生的源头进行捕获和处理。
比如,如果在一个函数内部进行了可能会引发异常的操作,那么就在这个函数内部首先进行异常的检测和处理。
这样做的好处是可以避免异常在程序中传播得太远,导致更多的代码受到影响,同时也能够更有针对性地解决问题。
第二个原则是“只处理能处理的异常”。
并不是所有的异常我们都有能力或者应该在当前的位置进行处理。
有些异常可能需要在更高层次的逻辑中或者特定的模块中进行统一处理。
如果在一个不适合处理某个异常的地方强行处理,可能会导致处理方式不当,甚至掩盖了真正的问题。
“提供有意义的错误信息”是异常处理的另一个重要原则。
当异常发生时,我们应该向用户或者其他开发者提供清晰、准确且有用的错误信息。
这样可以帮助他们更快地理解问题所在,从而更容易地进行调试和修复。
一个好的错误信息应该包括异常的类型、发生的位置以及可能的原因等。
接着是“避免捕获过于宽泛的异常”。
有些开发者为了省事,会使用类似“catch(Exception e)”这样的方式来捕获所有类型的异常。
然而,这样做会隐藏很多潜在的问题,并且使得异常处理变得混乱和难以维护。
我们应该尽量明确地捕获特定类型的异常,以便能够更精确地进行处理。
“保持异常处理的简洁性”也是不可忽视的原则。
异常处理的代码应该简洁明了,不应该包含过于复杂的逻辑。
如果异常处理的部分变得过于复杂,会使得代码的可读性降低,并且容易引入新的问题。
C语言中的异常处理方法
C语言中的异常处理方法异常处理在编程中起着至关重要的作用,它能够有效地帮助程序员识别并处理程序中可能出现的错误。
对于C语言而言,异常处理是一种非常有用的技术,本文将介绍C语言中几种常见的异常处理方法。
1. 错误码错误码是最常见的异常处理方法之一,它通过定义一系列的错误码来表示程序中可能出现的错误情况。
在C语言中,错误码通常以负数的形式表示,如-1、-2等。
程序在执行过程中,如果遇到错误情况,可以返回相应的错误码,使得调用方能够根据错误码来进行相应的处理。
例如,假设一个函数用于打开一个文件,在打开失败时可以返回错误码-1,让调用方知道打开文件时发生了错误,从而采取适当的处理措施。
2. 异常信号异常信号是一种用于处理程序中出现异常情况的机制,它的作用是在程序执行过程中发出一个信号,告知程序需要进行异常处理。
在C语言中,可以使用信号处理机制来捕获并处理这些异常信号。
通过使用signal函数可以注册一个信号处理函数,当程序接收到指定的信号时,会执行该信号处理函数。
其中,常见的异常信号包括SIGSEGV(段错误)、SIGFPE(浮点错误)等。
通过使用异常信号机制,我们可以对程序中出现的异常进行有效的响应和处理。
3. 异常处理语句(try-catch)尽管C语言本身并没有提供类似于C++和Java中的try-catch语句,但是我们可以通过使用setjmp和longjmp函数来模拟异常处理的功能。
setjmp函数用于设置一个跳转点,而longjmp函数用于跳转到指定的跳转点。
在程序执行过程中,如果遇到异常情况,可以使用longjmp函数跳转到事先设置的跳转点,从而实现异常处理的效果。
这种异常处理方法虽然相对复杂,但在某些情况下是非常有用的。
4. 异常处理库为了更方便地处理异常,一些库函数和框架提供了专门的异常处理机制。
例如,C语言的标准库中提供了setjmp.h和signal.h等头文件,它们提供了一些函数和宏来支持异常处理。
C++语言程序设计教程第13章 异常处理和命名空间
1.语法格式
try-catch语句的进一步说明: ③ 如果catch语句块的格式为: catch (…) {异常处理语句} 表示捕捉任何类型的异常,但必须放在 try-catch结构中的最后,相当于“其他”。 如果把它作为第一个catch子句,则后面的 catch子句都不起作用。catch (…)语句可以 单独使用。
1.语法格式
catch后面的圆括号中只能有一个形参,但 该形参是可选的,所以一般只写异常的类型。 但在捕获异常的同时还要利用throw抛出的值, catch就必须带有参数,表示指定变量或类对象。 如: catch(int y) {cout<<"throw"<<y;} 如果不想得到一个拷贝值,而是希望获得 表达式本身的值,则需把catch的参数声明为引 用。如:catch(int &)
13.1.3 构造函数和析构函数的异常处理
如果系统没有完整地创建一个类对象, 系统不会调用析构函数来释放它,这样构造 函数发生异常前所创建的类对象成员有时不 被释放。 构造函数的异常处理方法是:在构造函 数发生异常时,需要保证已创建的类对象成 员能够被释放,然后才抛出异常。
13.1.3 构造函数和析构函数的异常处理
1.语法格式
try-catch语句的进一步说明: ① 一个函数可以只有try语句块而无 catch语句块,也就是在此函数中只检查并不 处理,把catch语句块放在其他函数中。
1.语法格式
try-catch语句的进一步说明: ② 一个try-catch语句中只能有一个try语 句块,但却可以有多个catch语句块,以便与 不同的异常类型匹配。catch只检查所捕捉异 常的类型,并不检查它们的值,这也是为什 么对于不同异常throw必须抛出不同类型异 常的原因。
编码中的异常处理
编码中的异常处理
异常处理是编程中常见的一种技术,它可以有效地避免程序发生错误,保证程序的正常运行。
以下是异常处理的主要内容。
一、定义异常
在编程中,我们会遇到许多不可预料的问题,造成程序的执
行出现了错误,这就是异常。
所以,在编写程序时,必须要考虑这类异常情况,并在程序中进行处理。
二、定义异常处理流程
异常处理流程是指在编程中,当程序出现异常时,程序将根据规定的流程对其进行处理。
比如说,首先对发生异常的代码块进行捕捉,然后显示出错信息,最后处理错误。
三、定义异常类型
由于异常的发生原因会有很多种,所以,在编程中,要根据
不同的异常类型进行异常处理。
比如说,超出字符串长度的异常,文件读写异常,网络故障异常等等。
四、定义异常处理方法
不同的异常处理方法会有不同的处理效果。
比如说,try catch 语句可以捕捉未经处理的异常,并且可以在异常发生具体信息;finally 语句用于在异常发生后,负责释放或者重新设置一些资
源;throws 关键字则可以用于抛出已经捕获的异常,以便上层程序对其进行处理。
五、总结
综上所述,异常处理是编程中一种常见的技术,它的作用在于避免程序发生错误,保证程序的正常运行。
异常的处理主要涉及定义异常、定义异常处理流程、定义异常类型以及定义异常处理方法等。
希望本文能够为大家在异常处理上提供一些参考。
异常处理PPT课件
这类异常并非因设计或实现引起,是无法避免的。 但一般情况下,程序员应该提供相应的代码捕捉和 处理。
14
受检查的异常和不受检查的异常: 受检查的异常
Exception类及其非RuntimeException子类属于受 检查的异常;
9) System.out.println("After method.");
10) } 11) }
6
Exception in thread "main" ng.ArithmeticException: / by zero at ExceptionDivideBy0.method(ExceptionDivideBy0.java:4) at ExceptionDivideBy0.main(ExceptionDivideBy0.java:8)
一般情况下,程序员可不必理会这类异常,它们 虽然很严重,但很少发生。
12
(2) RuntimeException类及其子类: 表示设计或实现 方面的问题,例如:
● ArithmeticException(算术运算异常): 算术运算时发生 的异常情况,如整数相除,除数为零。 ● ClassCastException(强制类型转换异常): 把一个对象 引用转换成一个不合适的类型,如把一个对象引用转换成某 个子类类型。 ● NullPointerException(空引用异常): 需要对象引用时使 用了一个null引用。 ● ArrayIndexOutOfBoundsException(数组下标越界异常): 下标值超出了数组大小。 ● NumberFormatException(数字格式异常): 试图将非数 字格式字符串转换成数值。
C#LectureNotes_第13章
13.2 异常处理
13.2.1 异常处理的一般步骤
生 抛出 自 动
异常类
成
当异常发生时,首先抛出异 常,可以由系统自动生成异 常对象,也可以由用户强制 抛出异常对象;将异常对象 抛给运行时系统以后,系统 就开始捕捉异常,如果捕获 到该异常对象,则进行相应 的处理,找不到处理代码, 则终止系,退出程序。
13.1.2 异常的层次结构
System.Exception是C#异常的基类,其派生类包括以下几类: System.ApplicationException:最重要的派生类之一。它由用户程序而不是 由公共语言运行库引发,作为一种区分应用程序定义的异常与系统定义的异常 的方法而提供。 System.IO.IsolatedStorage.IsolatedStorageException:独立存储异常,在缺 少证据或无效操作时发生。 System.Runtime.Remoting.MetadataServices.SUDSGeneratorException:生 成Web服务描述语言WSDL的过程中发生错误时将引发的异常,由远程处理 WSDL生成器生成。 System.Runtime.Remoting.MetadataServices.SUDSParserException:分析 Web服务描述语言WSDL的过程中发生错误时将引发的异常,由远程处理 WSDL分析器生成。 System.SystemException:最重要的派生类之一。当发生非致命的、可由用 户程序恢复的错误时,公共语言运行时引发该类对象。 System.Windows.Forms.AxHost.InvalidActiveXStateException:引用处于无 效状态的 ActiveX 控件时引发的异常。
001223_异常处理_xgye
第10章 异常处理 10.1 异常的概念 10.2 异常的基本思想 10.3 异常的实现 10.4 异常处理的规则 10.5 多路捕获 10.6 异常处理机制 10.7 使用异常的方法
10.2 异常的基本思想
第10章 异常处理 10.1 异常的概念 10.2 异常的基本思想 10.3 异常的实现 10.4 异常处理的规则 10.5 多路捕获 10.6 异常处理机制 10.7 使用异常的方法
10.2 异常的基本思想
异常的基本思想: (1) 实际的资源分配(如内存申请或文件打 开)通常在程序的低层进行,如图10-1中 的k( )。 (2) 当操作失败、无法分配内存或无法打开 一个文件时,在逻辑上如何进行处理通 常是在程序的高层,如图10-1中的f( ), 中间还可能有与用户的对话。 (3)异常为从分配资源的代码转向处理错误 状态的代码提供了一种表达方式。如果 还存在中间层次的函数,如图10-1中的 g( ),则为它们释放所分配的内存提供了 机会,但这并不包括用于传递错误状态 信息的代码。
第10章 异常处理 10.1 异常的概念 10.2 异常的基本思想 10.3 异常的实现 10.4 异常处理的规则 10.5 多路捕获 10.6 异常处理机制 10.7 使用异常的方法
10.2 异常的基本思想
C++异常处理的目的,是在异常发 生时,尽可能地减小破坏,周密地 善后,而不去影响其它部分程序的 运行。这在大型程序中是非常必要 的。
第10章 异常处理 10.1 异常的概念 10.2 异常的基本思想 10.3 异常的实现 10.4 异常处理的规则 10.5 多路捕获 10.6 异常处理机制 10.7 使用异常的方法
10.4 异常处理的规则
以catch开始的程序块是异常处理程序, 编写异常处理程序的规则是:
异常处理技巧和原则
异常处理技巧和原则Java中的异常机制是指:当程序在运⾏过程中遇到意外情况时会⾃动抛出⼀个Exception对象来通知程序,程序收到这个异常通知后可以采取各种处理措施,这种机制能使程序更加健壮,可读性更⾼。
本⽂就来讲讲异常处理的相关知识。
异常分类Java中的异常分为RuntimeException和CheckedException。
RuntimeException:程序运⾏过程中出现错误,才会被检查的异常。
例如:类型错误转换,数组下标访问越界,空指针异常、找不到指定类等等。
CheckedException:来⾃于Exception且⾮运⾏时异常都是检查异常,编译器会强制检查并通过try-catch块来对其捕获,或者在⽅法头声明抛出该异常,交给调⽤者处理。
常见的checked异常有FileNotFoundException和InterruptedException等。
Error和Exception的区别在谈到Exception时,经常会涉及到Error。
Error和Exception存在如下的区别:Error是指系统中的错误,程序员是不能改变和处理的,是在程序运⾏时出现的错误,只能通过修改程序才能修正。
Java中的Error⼀般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不⾜,⽅法调⽤栈溢出等。
对于这类错误的导致的应⽤程序中断,仅靠程序本⾝⽆法恢复和和预防,遇到这样的错误,建议让程序终⽌,调整代码或者虚拟机参数再重新启动程序;Exception(异常)是程序可以处理的。
遇到这类异常,程序员应该尽可能捕获处理异常,使程序恢复运⾏,⽽不应该随意终⽌异常。
实在不知道如何处理就向上抛出该异常留给调⽤者处理。
总结下:异常(Exception)是⼀种⾮程序原因的操作失败(Failure),⽽错误(Error)则意味着程序有缺陷(Bug)。
异常处理的原则1. 能处理的异常尽早处理对于能明确知道要怎么处理的异常要第⼀时间处理掉。
《C++程序设计案例教程》第十三章异常处理课件
运行结果
12.1 函数模板
程序分析
上述程序首先定义函数delta()计算Δ,如果Δ小于0,使用throw语句抛出异 常(程序中将Δ抛出),然后将可能出现异常的语句(如调用函数delta()的语 句)放在try后面的花括号中,并在catch语句块中包含对该异常的处理。程序 运行后,如果try语句块内没有发生异常,则catch子句不起作用;如果发生异 常,则对throw抛出的异常进行处理,catch子句的参数数据类型应与throw语 句后的表达式数据类型相同。
目录
知识讲解
C++的异常处理机制由三部分组成:检查(try)、抛出( throw)和捕获(catch)。将需要检查的语句放在try语句块中, throw用来当发生异常时发出一个异常消息,catch语句块用于捕获 throw抛出的异常信息,如果捕获到异常信息,就对其进行处理。 throw语句的语法格式为: throw 表达式; try-catch的结构为: try {
编程求解一元二次方程实根,要求进行异常处理,判断Δ (b2-4ac)是否大于0,成立则计算实根,否则重新输入。
目录
12.1 函数模板
源代码展示
#include "stdafx.h"
#include <iostream.h>
#include <math.h>
double delta(double a,double b,double c) //定义函数,计算Δ
异常处理
异常是指程序在运行过程中,由于使用环境的变化和用户误 操作而产生的错误。异常处理是指在程序设计过程中,针对可预 测的异常编写相应的处理代码,防止异常发生后造成严重的后果。
目录
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} 为MP3Collect程序添加异常处理功能 了解了有关CBuilder中异常处理的基础知识后,下面我们就来为 Mp3Collect添加异常处理代码,以提高程序的容错性和强壮性。 实际上,由CBuilder自动生成的程序框架中已经包含了异常处理代 码,在应用程序入口单元文件MP3Collect.cpp中,入口函数WinMain()便 包含有try和catch代码段。不过,仅仅依靠这些缺省的异常处理还不 够,我们还需要针对不同的错误情况分别进行处理,才能保证程序运行 的可靠性。 在Mp3Collect中,可能出现的异常情况主要是由媒体播放器控件产生 的EMCIDeviceError和进行文件操作时产生的各种文件操作异常,具体 地说,可能产生异常的函数主要有btnShowAllClick()、btnFindClick()、 SaveFile()、btnFileNameClick()、mnuAddClick()、 ListView1SelectItem()、MediaPlayer1Click()、Timer1Timer()、 PlayTheSong()等。不过,为了简化程序代码,心铃准备统一采用了 Exception类来捕捉所有的VCL异常对象,并利用对象的类名称属性 ClassName来显示该异常的类别。 BtnFileNameClick()的主要功能是运行打开文件对话框OpenDialog1, 并将获取的文件名赋给文件名称编辑框和媒体播放器,其中,从 OpenDialog1->Execute()开始就可能产生异常,下面是添加了异常处理后 的btnFileNameClick(): void __fastcall TMainForm::btnFileNameClick(TObject *Sender) { try{//标志可能产生异常的代码段 if(OpenDialog1->Execute()) { MediaPlayer1->FileName=OpenDialog1->FileName; edtFileName->Text=OpenDialog1->FileName; edtSongName>Text=ChangeFileExt(ExtractFileName(OpenDialog1>FileName),""); edtSingerName->Text=""; MediaPlayer1->Open(); } } catch(Exception &e){//异常信息由两部分组成:异常对象的类名称、 异常对象的错误消息 ShowMessage(AnsiString(e.ClassName())+ ": " + e.Message);
{ DoDefault=false;//取消缺省操作 m_bIsห้องสมุดไป่ตู้laying=false;//清除播放标志 Timer1->Enabled=false;//关闭时钟 EnableButtons(true);//使能命令按钮 ShowMessage(AnsiString(e.ClassName())+" Error IntToStr(MediaPlayer1->Error) + ": " + e.Message); } } Timer1Timer()与MediaPlayer1Click()的异常处理方式基本一致,也是 将函数体内原有的全部代码标志为try代码段,并在catch代码段中进行 清除播放标志、关闭Timer1等操作。另外,在时钟处理函数中应该尽量 缩短函数的执行时间,避免函数重入引起的问题,因此Timer1Timer()函 数的catch代码段最好不要显示异常信息,如果确实需要显示,必须在关 闭Timer1之后再显示。 由于PlayTheSong()被MediaPlayer1Click()和Timer1Timer()调用,而后 两个函数中的异常处理代码完全可以处理PlayTheSong()可能产生的异 常,因此就不需要再单独添加异常处理代码了。 最后,btnShowAllClick()、btnFindClick()、SaveFile()三个函数已经有 了基于传统的条件判断式的异常检测和异常处理代码,能够处理打开文 件不正常的情况,读者朋友可以自行练习一下,把这一部分的异常处理 改用try和catch代码段来实现。 本讲介绍了在CBuilder中进行异常处理的内容,不少初学 CBuilder(或其它编程语言)的朋友因为觉得异常处理很复杂或是用处 不大,就忽略了这部分内容,其实,异常处理的原理并不复杂,无非是 中断产生异常的程序代码,捕捉可能产生的异常并进行相应处理,掌握 了这一基本原理之后,就容易理解为什么要引入异常处理机制,以及如 何使用异常处理机制了。
常处理机制,微软公司提供的Win32结构化异常处理机制,以及基于 VCL的异常处理机制,后者是Borland公司建议在CBuilder编程中采用的 异常处理方式。 基于VCL的典型异常处理结构的形式如下所示: try{ //可能引起异常的代码段 } catch(Exception &e){ //对异常进行处理的代码 } 其中try和catch为C++关键字。try用于标志可能产生异常的代码段 (Block),该代码段用try后紧跟的一对大括号{}包括在内。如果这段 程序在运行时产生了异常,系统会中止try代码段中的代码执行,并查找 相应的catch代码段,如果找到了合适的catch代码段,即表示错误被捕 捉到,这时相应的catch代码段被执行,如果没有找到合适的catch代码 段,即错误始终没有被捕捉到,则系统会调用VCL库按照缺省的方法来 处理异常。当然,如果try代码段在运行时一切正常,则catch代码段是 不会被调用的。 在上面的异常处理结构中,我们看到,catch语句带有一个参数 Exception &e,该参数是一个异常对象的引用。其中Exception是VCL库 提供的异常处理类,该类代表了VCL库对异常事件的一个封装。也许有 的朋友要问,catch语句中的Exception &e对象是哪里来的呢?整个程序 代码中没有该对象的声明或定义呀?这正是VCL异常处理机制的特点, 当异常产生时,VCL库会自动生成该异常对象,并将其作为参数调用合 适的catch代码段。 Exception类也是其它VCL异常处理类的基类。为了处理不同的异常 原因,CBuilder提供了多种异常处理类,例如,代表申请内存失败的 EOutOfMemory异常,代表除数为0的EDivByZero异常,代表文件打开 错误的EFOpenError,代表数据库操作错误的EDatabaseError,以及代表 多媒体操作错误的EMCIDeviceError等。 事实上,一个代码块可能产生不止一种类型的错误,这样,对一个 try代码段可以采用多个catch代码段。例如,一个try代码段内部可能产 生申请内存失败异常EOutOfMemory和打开文件错误EFOpenError,那么 我们可以使用两个catch语句来分别监视两种异常情况。采用多个catch 语句的优点在于,可以对不同类型的异常分别进行捕捉和处理,但有时 即使使用了多个catch语句后仍无法保证能够捕捉到所有的异常,这时可 以使用参数为省略号(...)的通用catch语句,它可以捕捉尚未捕捉的所有
任意类型的异常。 下面是使用多个catch及通用catch语句的典型例子,try代码段中进行 了打开文件操作、分配内存操作、文件读操作和整数除法操作,这些操 作都有可能引起异常,程序中对打开文件异常和分配内存异常分别进行 了处理,对剩下的异常则统一由catch(...)语句进行处理。 try{ FILE * fp=fopen("test.dat","rb");//可能出现EFOpenError类异常 BYTE * buf=new BYTE[1024];//可能出现EOutOfMemory类异常 int k,i=100,j=fread(buf,1024,1,fp);// 可能出现EReadError类异常 k=i/j; //可能出现EDivByZero类异常 fclose(fp); delete buf; } catch(EFOpenError &e){ ShowMessage("test.dat:打开文件错误"); } catch(EOutOfMemory &e){ ShowMessage("内存不足错误"); } catch(...){ ShowMessage("应用程序出现异常错误"); } CBuilder为VCL库提供了非常灵活的异常唤醒和异常处理机制,除了 由VCL库检测和产生异常之外,还可以由程序通过throw语句来强制产 生一个异常,例如下面的代码在检测到异常情况后,强制产生一个异 常,并初始化异常消息,交由catch代码段进行处理,后者将显示出现异 常的信息。在这段代码中,异常检测仍然采用的是传统的条件语句检测 方法,但异常处理则采用的是面向对象的异常处理方式。 try{ FILE * fp=fopen("test.dat","rb"); if(fp==NULL) //检测异常条件 throw Exception("test.dat:打开文件错误"); //创建异常对象, 并抛出异常对象 ...//正常的执行代码 } catch(Exception &e){ ShowMessage(e.Message);//显示异常信息
} } mnuAddClick()与btnFileNameClick()相似,此处不再重复。 ListView1SelectItem()在操作MediaPlayer1控件时容易产生异常,因此 try代码段中应包括对MediaPlayer1的操作,添加异常处理后的该函数如 下: void __fastcall TMainForm::ListView1SelectItem(TObject *Sender, TListItem *Item, bool Selected) { if(Item && Selected) { ……//其它操作 try{//try代码段包括对MediaPlayer1的操作 MediaPlayer1->FileName=edtFileName->Text; MediaPlayer1->Open(); } catch(Exception &e){ //异常消息由三部分组成:异常的类名称、MediaPlayer1的错误代 码及其错误信息 ShowMessage(AnsiString(e.ClassName())+" Error " + IntToStr(MediaPlayer1->Error) + ": " + MediaPlayer1>ErrorMessage); } } } MediaPlayer1Click()函数体内原有的全部代码都应该被包括在try之 内,并且在catch代码中,除了显示异常信息外,还需要清除播放标志, 并关闭Timer1。添加了异常处理代码的该函数如下: void __fastcall TMainForm::MediaPlayer1Click(TObject *Sender,TMPBtnType Button,bool &DoDefault) { try{ switch(Button){ ……//根据Button参数判断用户点击了什么按钮,进行相应的 处理 } } catch(Exception &e)//捷捉可能产生的异常