2

我编写了一个自定义 SDL GUI 工具包(源代码在http://sourceforge.net/projects/lkgui/files/上)并且我遇到了继承对象的问题。

当对象在主程序中时,不会调用构造函数,因此程序没有正确初始化对象,并且在某些命令后崩溃(具体来说,TStartGameButton 继承自 GUI_Canvas 继承自 GUI_Element 并且任何未在 GUI_Element 中定义的东西都会崩溃带有 EAccessViolation 的程序)。当对象被放置在一个单元内时,这个问题就消失了。

我知道我可以把它留在单元中,但这会导致一些丑陋的代码,希望可以避免。

有谁知道为什么会发生这种情况以及如何避免它?

4

2 回答 2

3

自 Delphi 2 发布以来,旧式 Delphi 对象已经被破坏,也许更早。当它们具有编译器管理类型的字段(例如string动态数组)时,它们不能很好地进行继承。2004 年在comp.lang.pascal.delphi.misc上有一个关于它的讨论。这是重现它的代码:

type
  TBase = object
  public
    s: string;
  end;

  TDerived = object(TBase)
  end;

procedure test;
var
  obj: TDerived; //okay for TBase!
begin
  assert(obj.s = '', 'uninitialized dynamic variable');
end;

事实上,这只是TBase偶然的,因为函数的序言代码是如何生成的。在该函数中添加额外的代码可能会使其崩溃。

确实,正如您所观察到的那样——旧式对象没有正确初始化。他们的字符串字段一开始并不是空字符串;相反,它们包含垃圾,因此如果不使用类似FillChar.

这似乎是由于变量是局部变量。单位范围(“全局”)变量似乎工作正常。在单元范围内声明但仅由单元的初始化部分或在程序范围内且仅在 DPR 文件的主开始-结束块中使用的变量被编译器视为局部变量,因此它们不会设置为 all -bits-zero 就像他们的全球同行一样。当您将变量声明移动到一个单元但继续在 DPR 文件中使用它时,它会提升到“全局”状态。

您的TGUI_Element类型有一个string名为 的成员DbgName,看起来这是您在类型层次结构中拥有的唯一字符串字段。把它拿出来,或者把它改成ShortString,我敢打赌你的崩溃会消失,至少是暂时的。

于 2010-01-27T14:56:36.543 回答
0

为什么要为所有对象提供单独的命名构造函数而不是使它们成为虚拟对象?

  type   tx = object
                constructor init; virtual;
                end;
         txx = object(tx)
                   constructor init; virtual; // like override in Delphi classes.
                  end;

如果您需要查看视觉层次结构,请查看 Free Vision,它几乎展示了 TP 对象模型的每个方面

糟糕,TP 模型中显然不可能有虚拟构造函数

于 2010-01-27T14:14:06.573 回答