提问人:Artik 提问时间:8/1/2013 更新时间:10/25/2023 访问量:3837
如何在 Delphi 中重载分配记录运算符
How to overload assign operator for record in Delphi
问:
我想制作使用动态数组的记录类型。
使用这种类型的变量 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)
有两个问题:
- 当我在 TMyRec 中不使用覆盖分配运算符时,A:=B 表示 A 和 B(它们的Inner_Array)指向同一个位置 记忆。
避免问题 1) 我想重载 assign 运算符 用:
类运算符 TMyRec.Implicit(source: TMyRec): TMyRec;
但是编译器(Delphi XE)说:
[DCC 错误]:E2521 运算符“隐式”必须在参数或结果类型中采用一种“TMyRec”类型
如何解决此问题。 我在 stackoverflow 上阅读了几篇类似的帖子,但它们对我的情况不起作用(如果我很好地理解它们的话)。
阿蒂克
答:
6赞
David Heffernan
8/1/2013
#1
赋值运算符不能重载。这意味着您正在尝试执行的操作是不可能的。
编辑:现在可以了 - http://docwiki.embarcadero.com/RADStudio/Sydney/en/Custom_Managed_Records#The_Assign_Operator
评论
0赞
Artik
8/1/2013
这是否意味着,没有办法捕获赋值 A:=B 并将数据从 A 复制到 B?
2赞
LU RD
8/1/2013
可以在动态数组上引入 COW 功能。这将在写入数组时处理克隆,就像类型工作一样。这有点乱,但我设法让它工作。我将很快发布代码。让我感到不安的主要事情是,像 ,等 这样的固有函数不可能作为运算符重载引入。String
SetLength
Length
0赞
Alexander Bokovikov
10/26/2018
#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.
评论
TMyRec.Clone
Inner_Array
A.Inner_Array[1] := 1;
Inner_Array