【问题标题】:How to overload assign operator for record in Delphi如何在 Delphi 中重载分配运算符以进行记录
【发布时间】:2013-08-01 12:57:06
【问题描述】:

我想制作使用动态数组的记录类型。

使用这种类型的变量 A 和 B 我希望能够执行操作 A: = B (和其他)并且能够在不修改 B 的情况下修改 A 的内容,如下面的代码片段:

    type
      TMyRec = record
        Inner_Array: array of double;
      public
        procedure SetSize(n: integer);
        class operator Implicit(source: TMyRec): TMyRec;
      end;

    implementation

    procedure TMyRec.SetSize(n: integer);
    begin
      SetLength(Inner_Array, n);
    end;

    class operator TMyRec.Implicit(source: TMyRec): TMyRec;
    begin
    //here I want to copy data from source to destination (A to B in my simple example below)
    //but here is the compilator error
    //[DCC Error] : E2521 Operator 'Implicit' must take one 'TMyRec' type in parameter or result type
    end;


    var
      A, B: TMyRec;
    begin
      A.SetSize(2);
      A.Inner_Array[1] := 1;
      B := A;
      A.Inner_Array[1] := 0;
//here are the same values inside A and B (they pointed the same inner memory)

有两个问题:

  1. 当我不在我的 TMyRec 中使用覆盖分配运算符时,A:=B 表示 A 和 B(它们的 Inner_Array)指向同一个位置 记忆。
  2. 为了避免问题 1) 我想重载赋值运算符 使用:

    类运算符 TMyRec.Implicit(source: TMyRec): TMyRec;

但是编译器(Delphi XE)说:

[DCC 错误]:E2521 运算符“隐式”必须在参数或结果类型中采用一种“TMyRec”类型

如何解决这个问题。 我在 stackoverflow 上阅读了几篇类似的帖子,但它们在我的情况下不起作用(如果我理解它们的话)。

艺术

【问题讨论】:

  • 引入TMyRec.Clone 函数。
  • 你应该让你的Inner_Array不可变;像A.Inner_Array[1] := 1; 这样的代码将被禁止 - 任何对Inner_Array 的写入都应该创建一个新的数组实例。另请阅读sergworks.wordpress.com/2013/04/10/… 以获得更多提示。
  • @user246408 不可变向量/矩阵类型通常不方便并导致性能不佳。例如,许多矩阵算法都在原地运行。
  • 谢谢你。我相信你的意见。

标签: delphi operator-overloading assignment-operator


【解决方案1】:

不可能重载赋值运算符。这意味着您尝试做的事情是不可能的。


编辑:现在可以 - http://docwiki.embarcadero.com/RADStudio/Sydney/en/Custom_Managed_Records#The_Assign_Operator

【讨论】:

  • 是不是说,没有办法捕捉赋值A:=B并将数据从A复制到B?
  • 可以在动态数组上引入 COW 功能。这将在写入数组时负责克隆,就像String 类型一样。这有点乱,但我设法让它工作。我会尽快发布代码。令我不安的主要是 SetLengthLength 等内部函数不能作为运算符重载引入。
【解决方案2】:

唯一已知的方法是使用指针,这是不安全的,因此您必须了解自己在做什么。

是这样的:

type
  PMyRec = ^TMyRec;
  TMyRec = record
    MyString : string;
    class operator Implicit(aRec : PMyRec) : TMyRec;
  end;
....
class operator TMyRec.Implicit(aRec : PMyRec) : TMyRec;
begin
  if aRec = nil then // to do something...
    raise Exception.Create('Possible bug is here!');
  Result.MyString := aRec^.MyString;
end;

调用示例应如下所示:

var
  aRec1, aRec2 : TMyRec;
begin
  aRec1.MyString := 'Hello ';
  aRec2.MyString := 'World';
  writeln(aRec1.MyStr, aRec2.MyStr);
  aRec2 := @aRec1;
  writeln(aRec1.MyStr, aRec2.MyStr);
end.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 2020-09-11
    • 2012-10-23
    相关资源
    最近更新 更多