(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

相关文章

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

Java异常架构Exception(异常)详解

《Java异常架构Exception(异常)详解》:本文主要介绍Java异常架构Exception(异常),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. Exception 类的概述Exception的分类2. 受检异常(Checked Exception)

Java报NoClassDefFoundError异常的原因及解决

《Java报NoClassDefFoundError异常的原因及解决》在Java开发过程中,java.lang.NoClassDefFoundError是一个令人头疼的运行时错误,本文将深入探讨这一问... 目录一、问题分析二、报错原因三、解决思路四、常见场景及原因五、深入解决思路六、预http://www

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES

最新Spring Security实战教程之Spring Security安全框架指南

《最新SpringSecurity实战教程之SpringSecurity安全框架指南》SpringSecurity是Spring生态系统中的核心组件,提供认证、授权和防护机制,以保护应用免受各种安... 目录前言什么是Spring Security?同类框架对比Spring Security典型应用场景传统

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

OpenManus本地部署实战亲测有效完全免费(最新推荐)

《OpenManus本地部署实战亲测有效完全免费(最新推荐)》文章介绍了如何在本地部署OpenManus大语言模型,包括环境搭建、LLM编程接口配置和测试步骤,本文给大家讲解的非常详细,感兴趣的朋友一... 目录1.概况2.环境搭建2.1安装miniconda或者anaconda2.2 LLM编程接口配置2

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx