我编写了一个自定义 SDL GUI 工具包(来源位于 http://sourceforge.net/projects/lkgui/files/ ),但我遇到了继承对象的问题。
当对象位于主程序中时,不会调用构造函数,因此程序无法正确初始化对象,并且在执行某些命令后会崩溃(具体来说,TStartGameButton 继承自 GUI_Canvas 继承自 GUI_Element 以及任何未定义的内容) GUI_Element 中的程序因 EAccessViolation 而崩溃)。当对象放置在一个单元内时,这个问题就消失了。
我知道我可以将其留在单元中,但这会导致一些丑陋的代码,但希望可以避免。
有谁知道为什么会发生这种情况以及我如何避免它?
最佳答案
自 Delphi 2 发布(也许更早)以来,旧式 Delphi 对象已被破坏。当它们具有编译器管理类型的字段(例如字符串或动态数组)时,它们不能很好地继承。有a discussion about it 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 文件的主开始结束 block 中使用的变量,将被编译器视为局部变量,因此它们不会设置为 all -bits-zero 就像他们的全局同行一样。当您将变量声明移至某个单元但继续在 DPR 文件中使用它时,它会提升为“全局”状态。
您的 TGUI_Element
类型有一个名为 DbgName
的 string
成员,看起来这是类型层次结构中唯一的字符串字段。将其删除,或者将其更改为 ShortString
,我敢打赌您的崩溃就会消失,至少会暂时消失。
关于delphi - 对象在主程序中崩溃,但在移动到单元时不会崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2147114/