【问题标题】:How to get the type information of a record by its pointer in Delphi XE?Delphi XE中如何通过指针获取记录的类型信息?
【发布时间】:2011-10-19 17:48:09
【问题描述】:

如果我有一个 TList,其中包含许多不同记录类型的指针,我如何访问 TList 中不同记录的值?

有什么方法可以获取那些引用的记录的记录类型或类型信息吗?

我目前正在使用 Delphi XE。

【问题讨论】:

  • 我对 RTTI 一无所知,但我认为指向记录的指针不会携带类型信息。我错了吗?
  • 试试这个 PRecord(List[i])^.member 其中 PRecord 是 ^Yourdefinedrecord ...我不太明白这个问题...
  • @opc0de 我认为问题在于您不知道列表中的类型的列表。否则它就像你的评论一样微不足道。
  • 好点不明白这个问题感谢您为我解决问题。

标签: delphi pointers delphi-xe record rtti


【解决方案1】:

您的不同记录类型需要一个共同的标题。然后,您可以首先将列表项指针转​​换为该标头类型,以确定接下来要转换的记录类型。例如:

type
  TRecType = (recA, recB, recC);

  PRecHeader = ^TRecHeader;
  TRecHeader = record
    RecType: TRecType;
    ...
  end;

  PRecordA = ^TRecordA;
  TRecordA = record
    Header: TRecHeader;
    IntValue: Integer;
  end;

  PRecordB = ^TRecordB;
  TRecordB = record
    Header: TRecHeader;
    StrValue: String;
  end;

  PRecordC = ^TRecordC;
  TRecordC = record
    Header: TRecHeader;
    DblValue: Double;
  end;

var
  PRec: Pointer;
begin
  PRec := List[Index];
  case PRecHeader(PRec)^.RecType of
    recA: use PRecordA(PRec)^.IntValue as needed ...
    recB: use PRecordB(PRec)^.StrValue as needed ...
    recC: use PRecordC(PRec)^.DblValue as needed ...
  end;
end;

【讨论】:

  • 只使用变体记录而不是重新实现它会容易得多。
  • 即使是变体记录也需要一个位于变体区域之外的标头值,以了解要访问的变体数据的哪一部分。
  • 是的,但语法更简洁。当然如果你使用托管类型,比如字符串,那么你就不能使用变体记录!
  • 原始多态性。 FPC 1.0.x 的编译器树是这样的。
【解决方案2】:

你真的不能这样做。与 Delphi 对象不同,记录不携带任何 RTTI。如果您正在混合一堆不同类型的数据,并且希望能够在运行时找出它们是什么类型的数据,那么最好的办法就是简单地使用对象,它继承 TObject.ClassType 和少数其他例程使这项任务变得简单。

如果您出于某种原因确实需要使用记录,则必须在每条记录的开头使用不会更改的自定义标记。我正要描述这个系统,但看起来 Remy 打败了我。但这带来了足够的开销,同样,您也可以只使用对象,因为一旦您在这条路上走得很远,您基本上就是在重新实现很多 TObject

【讨论】:

    【解决方案3】:

    我强烈建议使用Contnrs 单元中的TObjectList 对象。 (它在 Delphi XE 中还存在吗?)这是基于 TList,但可以为您提供 TObject 引用而不是指针。这是一个细微的差别,但允许您在列表项上直接使用 isas 运算符。

    【讨论】:

    • TObjectList 在 XE 中仍然存在,但对记录指针并没有真正的帮助。
    • @TOndrej 我认为建议是远离不携带类型信息的记录。
    【解决方案4】:

    在 {$M+} 中使用对象帕斯卡风格怎么样?这将消除 TObject 的开销

    {$M+}
    
    TRecordA = object
    end;
    
    TRecordB = object
    end;
    
    {$M-}
    

    【讨论】:

    • 这里可能有一个很好的答案,但需要一些详细说明
    猜你喜欢
    • 2011-12-11
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多