为什么在Delphi中析构函数被命名为"Destroy"?

8
在Delphi中,析构函数通常命名为“Destroy”,但据我所知,您也可以:
- 以不同的名称命名析构函数 - 拥有多个析构函数
这种实现方式有什么原因?以不同名称/多个析构函数可能有哪些用例?

2
很可能这是为了保持一致性。但我从来没有看到过除了重写虚拟的 Destroy 之外做任何其他事情的情况。 - David Heffernan
1个回答

8
在理论上,您可以手动调用不同的析构函数来释放不同的外部资源,比如打破引用计数循环、删除或关闭文件等。
此外,由于Object Pascal语言没有那些神奇的new/delete操作,所以只需要一些标识符来调用对象的处理过程。
我更喜欢回顾一下。
“Turbo Pascal with Objects”风格的对象都有一个“神奇”的Dispose过程,但需要显式指定要调用的析构函数,因为语言本身不知道选择哪个。类似地,“神奇”的New过程必须提供手动选择的构造函数。 然而,这违反了DRY原则:编译器知道我们正在调用析构函数或构造函数,但是我们还必须额外调用那些“New”和“Dispose”函数。理论上,这可能有助于解耦内存分配和信息馈送,并以任何我们喜欢的方式组合它们。但我不认为这个功能实际上被广泛使用过。

有趣的是,苹果Objective C中使用相同的设计。您首先为对象分配内存,然后为该新实例调用构造函数:http://en.wikipedia.org/wiki/Objective-C#Instantiation

当Delphi简化这个模型时,做出了一些决策,使事情更加简单(和统一)。内存[de]分配策略转移到类级别,而不是调用站点。这使得调用“New”和命名构造函数的冗余非常对比。必须放弃其中之一。

C++/C#/Java选择保留特殊的语言级别关键字,使用重载函数提供不同的构造函数。也许这符合美国风格的计算机语言。

然而,Pascal的核心有两个想法:冗长和小词汇量。可以说这些想法在其他类似于Scala的欧洲学派语言中也可以追踪。如果可能的话,关键字应该从语言本身中移除,并移到外部模块——可以添加或删除项目的库中。过载函数是在语言中引入得较晚的,早期的偏好肯定是有两个不同命名(自注释)的函数名称。

这两个想法可能导致Delphi删除“幻术”程序,并通过使用的函数名称推断出调用现场的对象创建/销毁。如果您调用MyVar.Destroy,编译器会查看.Destroy的声明,并知道我们正在删除对象。同样,由于CreateXXX的声明方式,它知道TMyType.CreateXXX(YYY,ZZZ)是一个对象实例化。

为了使c-tor和d-tor像C ++一样无名称,Delphi需要在语言层面引入另外两个关键字,就像C ++的newdelete一样。似乎没有明显的优势。至少就我个人而言,我更喜欢Delphi的方式。

PS. 我必须添加一个假设:我们谈论的是真正的 C++ 和 Delphi 语言,就像它们在 1995 年左右一样。它们只为堆分配的对象提供手动内存控制,没有垃圾回收和自动引用计数。您不能通过将变量赋值为 nil/NULL 指针来触发对象销毁。


有名字的构造函数?所以我可以有一个类 CMyClass,带有一个构造函数 ABetterNameIKnow?怎么做?如果没有关键字和命名构造函数,你会如何实现? - Arioch 'The
该类的构造函数被命名为CMyClass::CMyClass。 - David Heffernan
@DavidHeffernan这意味着它们没有命名。命名是指我按我的选择进行命名。这就是像beginwhile关键字的命名方式。它们也是标识符,因此像您的示例中一样进行命名。仅它们的范围比:CMyClass的范围稍微广泛一些。 - Arioch 'The
我仍然不同意你在最后一段中的说法。请证明没有新的语言关键字是不可能实现ctor/dtor的。 - David Heffernan
请给我展示一个实际语言中如何“完美地在没有关键字支持的情况下完成”。昨天我所犯的错误是手动内存控制,在Delphi或C++中没有ARC或GC。现在,我们必须创建一个表达式,其评估将触发任何给定但事先未知的对象的销毁。var o: TObject; - 我如何处理它而不需要任何专门用于它的标识符?既没有语言级操作也没有RTL级固定方法名称? - Arioch 'The
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接