(delphi11最新学习资料) Object Pascal 学习笔记---第9章第5节(异常与构造函数)

本文主要是介绍(delphi11最新学习资料) Object Pascal 学习笔记---第9章第5节(异常与构造函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

9.5 异常与构造函数

​ 围绕异常还有一个稍微高级一点的问题,即当异常在对象的构造函数中产生时会发生什么情况。并非所有 Object Pascal 程序员都知道,在这种情况下,将调用对象的析构函数(如果有的话)。

​ 这一点很重要,因为它意味着一个部分初始化的对象可能会被调用析构函数。如果想当然地认为内部对象存在于析构函数中,因为它们是在构造函数中创建的,那么在出现实际错误时,可能会陷入一些危险的境地(即在第一个异常处理完毕之前引发另一个异常)。

​ 这也意味着,try-finally 的正确顺序应该是在代码块外创建对象,因为编译器会自动对其进行保护。因此,如果构造函数失败,就没有必要释放对象。这就是为什么 Object Pascal 的标准编码方式是通过写入以下内容来保护对象:

AnObject := AClass.Create;
try// 使用对象...
finallyAnObject.Free;
end;

注解:类似的情况也发生在 TObject 类的两个特殊方法 AfterDestruction 和 BeforeConstruction 上,它们是为兼容 C++ 而引入的伪构造函数和伪析构函数(但在 Object Pascal 中很少使用)。请注意,如果 AfterConstruction 方法引发异常,就会调用 BeforeDestruction 方法(以及常规的析构函数)。

​ 鉴于我经常看到在析构函数中释放对象的错误,让我通过一个实际的演示来进一步说明这个问题以及实际的解决方法。假设你有一个包含字符串列表的类,你编写了以下代码来创建和销毁该类(ConstructorExcept 项目的一部分):

typeTObjectWithList = classprivateFStringList: TStringList;publicconstructor Create(Value: Integer);destructor Destroy; override;end;constructor TObjectWithList.Create(Value: Integer);
beginif Value < 0 thenraise Exception.Create('Negative value not allowed');FStringList := TStringList.Create;FStringList.Add(Value.ToString);
end;destructor TObjectWithList.Destroy;
beginFStringList.Clear;FStringList.Free;inherited;
end;

​ 乍一看,代码似乎是正确的。构造函数分配子对象,而析构函数恰当地释放子对象。此外,调用代码的编写方式是,如果在构造函数之后出现异常,则调用 Free 方法,但如果异常出现在构造函数中,则什么也不会发生:

varObj: TObjectWithList;
beginObj := TObjectWithList.Create(-10);try// 进行一些操作finallyShow('Freeing object');Obj.Free;end;
end;

​ 这样行得通吗?绝对不行!当运行这段代码时,异常会在构造函数中出现,发生在创建字符串列表之前,系统会立即调用析构函数,试图清除不存在的列表,从而引发访问违规或类似错误。

​ 为什么会出现这种情况呢?同样,如果在构造函数中颠倒顺序(先创建字符串列表,后引发异常),一切都能正常工作,因为析构函数确实需要释放字符串列表。但这并不是真正的解决办法,只是一种变通方法。你始终应该考虑的是保护析构函数的代码,使其永远不会假定构造函数已被完全执行。下面就是一个例子:

destructor TObjectWithList.Destroy;
beginif Assigned(FStringList) thenbeginFStringList.Clear;FreeAndNil(FStringList);end;inherited;
end;

这篇关于(delphi11最新学习资料) Object Pascal 学习笔记---第9章第5节(异常与构造函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/905498

相关文章

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

Spring Boot集成SLF4j从基础到高级实践(最新推荐)

《SpringBoot集成SLF4j从基础到高级实践(最新推荐)》SLF4j(SimpleLoggingFacadeforJava)是一个日志门面(Facade),不是具体的日志实现,这篇文章主要介... 目录一、日志框架概述与SLF4j简介1.1 为什么需要日志框架1.2 主流日志框架对比1.3 SLF4

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决