【问题标题】:Delphi compiler bug? using "object", but with "record" it compilesDelphi编译器错误?使用“对象”,但使用“记录”编译
【发布时间】:2021-11-12 13:10:43
【问题描述】:

此代码无法编译(在 Delphi 7 和 Delphi XE2 上),并给出错误消息“需要 E2036 变量”。 但是如果我将“对象”更改为“记录”,那么它在 Delphi XE2 上编译得很好,因为它有高级记录。 我想在 Delphi 版本之间编写可移植代码,并在 D7 上使用“对象”,在带有 IFDEF 的 XE2 上使用“记录”,但在这种情况下看起来不可能。我错了,还是这是一个真正的编译器错误?

type

  TD = String;

  TC = object
  public
    V: String;
    function D: TD;
  end;

  TB = object
  public
    V: String;
    function C: TC;
  end;

  TA = object
  public
    V: String;
    function B: TB;
  end;

function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;

procedure Test;
var
  A: TA;
  s: string;
begin
  s := A.V; // Ok
  s := A.B.V; // Ok
  s := A.B.C.V; // "E2036 Variable required", the cursor is between "C" and "."
end;

感谢大家的快速响应。令人惊讶的是,几分钟后我找到了解决方法。 “对象”必须至少有一个虚拟方法(并且它的大小不能为零,所以它必须有一个数据字段,但它不必像“V:字符串”那样是托管类型)。这个丑陋的代码可以在 Delphi 7 和 Delphi XE2 上编译,如果 HAS_ADVANCEDRECORD 已定义。

{.$define HAS_ADVANCEDRECORD}

type

  TE = String;

  TD = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function E: TE; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TC = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function D: TD; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TB = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function C: TC; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

  TA = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
  public
    V: String;
    function B: TB; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
  end;

function TD.E: TE; begin end;
function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;

procedure Test;
var
  A: TA;
  s: string;
begin
  s := A.V; //* Ok
  s := A.B.V; //* Ok
  s := A.B.C.D.E; //* Solved: "E2036 Variable required"
end;

其实我想玩一个流畅的语法 sql 查询生成器,高级记录比 TObject 有优势。也就是说,它们不需要生命周期管理。一个自然的解决方案是在这里使用接口,但我总是遇到麻烦。

我想,更值得提高我对接口的了解...

【问题讨论】:

  • 使用object 已过时。使用recordclass
  • 如果你想为 Delphi 7 和 XE2 编写代码,你可能需要考虑一些其他的事情,例如。就像在 Delphi 7 中的字符串类型是 ANSI,但在 XE2 中是 Unicode!
  • @DelphiCoder Delphi 7 不支持增强的记录,因此类或过时的对象样式在最不方便时会失败。 (上面的代码应该可以正常编译。这并不意味着编译器中存在错误。但该错误不太可能得到修复。)
  • @malom: TLabel 不是一个对象,它是源代码中的一个类 (TLabel = class)。也是一个例外。其实一直回到Delphi 1,连TObject都是类,不是对象。它在 VCL 源代码中也被定义为 TObject = class。对象是否可以移动到一个类 - 自 Delphi 1 发布以来,对象已被弃用,并且只是为了向后兼容(应该在 20 年前被放弃)。
  • Per Delphi 的"Object Types" documentation:“对象类型仅支持向后兼容。不建议使用它们。object 在 Delphi 1 引入之前存在于 Turbo Pascal @ 987654331@。在所有版本的 Delphi 中,引用类型使用 class,值类型使用 record。忽略 object 存在。

标签: object delphi record


【解决方案1】:

这是一个错误。你可以提交一个错误报告,它至少会记录它。但是,我严重怀疑 Embarcadero 是否会投入更多资源来修复它,而且无论如何这不会帮助您使用旧版本的 Delphi。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-13
    • 2015-12-24
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多