代码之家  ›  专栏  ›  技术社区  ›  Max

Delphi(Win32)中的相互引用记录

  •  9
  • Max  · 技术社区  · 14 年前

    在Delphi中是否有创建相互引用记录的方法?下面是代码的简化版本:

    MyRec1 = record
      arr: MyRec2Array;
    end;
    
    MyRec2 = record
      mr: MyRec1;
    end;
    
    MyRec2Array = array of MyRec2;
    

    MyRec2 = record;
    

    在Delphi for Win32中不起作用。

    有什么建议吗?

    3 回复  |  直到 14 年前
        1
  •  14
  •   Mason Wheeler    14 年前

    记录是值类型,而不是引用类型。这意味着所有用作较大数据结构成员的记录都内联放置在结构本身中,而不是作为指针。试图创建两个相互包含的记录会使编译器在试图找出记录的结构时陷入无限循环。这可能就是为什么不能向前声明记录的原因,即使尝试在此处插入引用类型(动态数组),也不能违反语言规则。

    但您可以将指向记录类型的指针声明为正向声明,如下所示:

    PMyRec2 = ^MyRec2
    ...
    MyRec2 = record
      ...
    end;
    

        2
  •  4
  •   gabr    14 年前

    虽然我完全同意梅森的观点,但有一种方法可以绕过限制。基本上,在声明MyRec2之后,您可以使用record helper来定义必要的功能。

    type
      MyRec1 = record
        arr: array of byte;
      end;
    
      MyRec2 = record
        mr: MyRec1;
      end;
    
      MyRec1Helper = record helper for MyRec1
        procedure AllocateMyRec2(numItems: integer);
        function  GetMyRec2(i: integer): MyRec2;
        procedure SetMyRec2(i: integer; const value: MyRec2);
        property Rec2[i: integer]: MyRec2 read GetMyRec2 write SetMyRec2;
      end;
    
    procedure MyRec1Helper.AllocateMyRec2(numItems: integer);
    begin
      SetLength(arr, numItems * SizeOf(myRec2));
    end;
    
    function MyRec1Helper.GetMyRec2(i: integer): MyRec2;
    begin
      Move(arr[i*SizeOf(MyRec2)], Result, SizeOf(MyRec2));
    end;
    
    procedure MyRec1Helper.SetMyRec2(i: integer; const value: MyRec2);
    begin
      Move(value, arr[i*SizeOf(MyRec2)], SizeOf(MyRec2));
    end;
    
    var
      my: MyRec2;
    
    begin
      my.mr.AllocateMyRec2(2);
      my.mr.Rec2[0].mr.AllocateMyRec2(3);
    end.
    
        3
  •  4
  •   kludg    14 年前

    这个问题对我来说就像一个笑话——它不是关于相互引用,而是关于一个无限类型定义循环。至于相互引用,可以通过在记录中定义类型来解决(我使用了Delphi2009):

    type
      MyRec2 = record
      type
        MyRec2Array = array of MyRec2;
      type
        MyRec1 = record
          arr: MyRec2Array;
        end;
      var
        mr: MyRec1;
      end;
    

    但如何使用上述记录类型?真有趣。:)

    procedure TForm1.Button1Click(Sender: TObject);
    var
      R: MyRec2;
    
    begin
      SetLength(R.mr.arr, 1);
    //  R.mr.arr[0]:= ???;
    end;