【问题标题】:What's the damage from calling inherited incorrectly?错误地调用继承有什么损害?
【发布时间】:2011-12-31 19:46:57
【问题描述】:

在寻找 Delphi XE 程序中高度间歇性的内存损坏时,我发现了一个类构造函数,它初始化了类中的一些字段,并且 then 调用继承。我相信初始化是在第一次编写构造函数之后添加的,并且不小心在错误的地方。我现在已将其更正为先调用继承。内存损坏的异常几乎总是发生在此类的方法中。

问题:这个错误是否可能导致间歇性内存损坏?在跟踪代码时,似乎没有,但我真的希望这个修复能够解决间歇性问题。解决问题后一段时间没有出现,并不能证明它已经消失了。

一些代码:

Tmyclass = class
  ctype : integer;
  ts : tstringlist;
  th : thandle;
public
  Constructor Create;
  Destructor Destroy; override;
  ...
end;

Constructor Tmyclass.Create;
begin
  ctype := 3;
  doinit;
  inherited;
end;

【问题讨论】:

  • 给我们看一些代码。各种事情都可能是错的,也可能不是。

标签: delphi


【解决方案1】:

以下是创建对象的典型步骤:

  • 对象实例的内存分配;
  • 用零填充所有内存(以初始化所有字段,尤其是字符串);
  • 调用所有嵌套的构造函数,从最新的孩子开始,让inherited 调用每个父级 - 这就是为什么你应该在构造函数和析构函数中都写inherited

所以,inherited 调用父方法 - 您甚至可以指定父级别,或者如果您确定可以这样做(但可能违反 SOLID 原则),则调用 none。

其实在调用constructor的时候,方法里面加了一个隐藏参数:

构造函数和析构函数使用与其他函数相同的调用约定 方法,除了一个额外的布尔标志参数被传递给 指示构造函数或析构函数调用的上下文。

构造函数调用的标志参数中的值为 False 表示 构造函数是通过实例对象调用的或使用 继承的关键字。在这种情况下,构造函数的行为类似于 普通方法。 a 的 flag 参数中的值为 True 构造函数调用表示构造函数是通过一个 类参考。在这种情况下,构造函数创建一个实例 Self 给出的类,并返回对新创建的类的引用 EAX 中的对象。

析构函数调用的标志参数中的值为 False 表示 析构函数是使用inherited关键字调用的。在这个 在这种情况下,析构函数的行为类似于普通方法。值为 True 在析构函数调用的标志参数中表示 析构函数是通过实例对象调用的。在这种情况下, 析构函数释放 Self 之前给出的实例 回来了。

flag 参数的行为就像它在所有其他参数之前声明一样 参数。在寄存器约定下,它在 DL 中传递 登记。在帕斯卡约定下,它被推到所有其他之前 参数。在 cdecl、stdcall 和 safecall 约定下,它是 在 Self 参数之前推送。

来源:official Delphi documentation

因此,您可以确定,无论在哪里调用 inherited,它都会得到安全处理。例如,在调用所有构造函数之前,字段的初始化(重置为 0)将只处理一次。

TObject.Create 默认构造函数(在 inherited 行中调用的构造函数)只是一个 begin end void 块,它什么都不做。在这里调用inherited 甚至不是必要/强制的,但这是一个好习惯,因为如果您更改对象层次结构,则可能最终需要它。

唯一的问题可能是在这个inherited 方法(例如ctype := 2)中设置了某些字段,在子项中设置之后 - 但这不是编译器的错,这取决于用户代码!

【讨论】:

    【解决方案2】:

    在调用继承的构造函数之前初始化某些字段不一定是错误。有时继承的构造函数会调用一些已被后代覆盖的虚方法,而这些新实现依赖于这些字段才能正确初始化。

    (我并不是说这是好的设计,但它不是错误。)

    【讨论】:

      【解决方案3】:

      在 Delphi 中,您可以在调用继承的构造函数之前初始化对象字段(在 Turbo Pascal 或“旧”对象模型中不起作用,但在 Delphi“新”对象模型中允许这样做)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-17
        • 2015-09-04
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 2013-02-16
        • 1970-01-01
        • 2015-08-03
        相关资源
        最近更新 更多