【问题标题】:Should I write in the destructor call to all it's fields' destructors in Delphi?我应该在 Delphi 中对所有字段的析构函数进行析构函数调用吗?
【发布时间】:2021-03-30 15:48:25
【问题描述】:
TB = Class;
TC = Class;
TA = Class
  Strict Private
      B : TB;
      C : TC;

  Public
      Constructor Create;
      Destructor  Destroy; Override;
      //something
End;

//something 

Constructor TA.Create;
B := TB.Create;
C := TC.Create;
End;

Destructor TA.Destroy;
B.Free;//needed?
C.Free;//needed?
End;

是否需要调用 Free 类的析构函数中的所有字段,或者不需要但冗长是一种很好的风格?

【问题讨论】:

  • 是的,但您不是在询问“某些语言” - 您是在询问 Delphi。以上对 Delphi 来说是正确的。
  • @J... 所说的对于您询问的情况(基础课程)是正确的。但是,如果您基于(继承)您的类TComponent,那么您可以编写代码以便分配所有者,然后由所有者负责销毁。这就是例如表单将清理其所有子组件。
  • @TomBrunberg 当然,其他情况也存在 - 创建一个实现接口的对象并将其存储在接口变量中无需显式释放对象,就像使用像 TObjectDictionary<T> 这样的结构一样还实现所有权层次结构。
  • 我想重点是对象的生命周期始终是您需要考虑的事情,并且仅仅因为在某些情况下您不必在代码中明确地自己做,您仍然必须明确考虑所有对象的生命周期,并确保它们将被适当地释放,无论是开发人员明确地释放,还是在某些情况下自动释放。它从来都不是全自动的,所以我们在设计新代码时永远不能忽视它。
  • 在析构函数中调用继承也很重要。如果您不这样做,则不会调用祖先析构函数,并且如果该析构函数实现了某些代码,这也会造成内存泄漏或其他问题。如果你的祖先是普通类,那么祖先析构函数什么也不做,但仍然习惯于调用继承——这就是冗长和一致有助于避免问题的地方。

标签: class oop delphi constructor pascal


【解决方案1】:

在您提供的示例代码中,您确实必须销毁您创建的对象。这是一般规则。

如果您的对象继承自 TComponent,并且当您调用 constructor 并传递所有者时,则该所有者负责销毁组件。但是你可以 - 如果你喜欢 - 也可以在你的 destructor 中释放它。

如果创建对象是因为它们被分配给interface 类型的变量(由对象实现),那么您不应该销毁(释放)它。这是因为接口是引用计数的,并且对象在没有更多引用时会自动释放。当然,对象必须正确实现引用计数(TInterfacedObject 是一个基类,如果您不想打扰引用计数,可以将其用作祖先。但这是另一回事)。

【讨论】:

    猜你喜欢
    • 2020-09-25
    • 2017-08-30
    • 2016-03-26
    • 1970-01-01
    • 2015-08-07
    • 2018-01-02
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多