为什么不能对类使用运算符重载?

问题描述 投票:2回答:3

我在TDateTime中遇到类运算符的问题。

type
  TDateTime = class(TObject)
  public
    class operator Add(a: TDateTime; b: TTimeSpan): TDateTime;
    class operator Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
end;

implementation

class operator TDateTime.Add(a: TDateTime; b: TTimeSpan): TDateTime;
begin
  result := TDateTime.Create(a.Ticks + b.Ticks);
end;

class operator TDateTime.Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
begin
  result := TDateTime.Create(a.Ticks - b.Ticks);
end;

错误发生在第四行

E2123预期的过程,功能,属性或VAR

我为Windows编写此代码。但是,如果仅适用于.net和iOS,我该如何针对Windows?

delphi syntax operator-overloading
3个回答
11
投票

可以在Windows的Delphi中使用运算符重载仅用于记录,不适用于类http://docwiki.embarcadero.com/RADStudio/Rio/en/Operator_Overloading_(Delphi)

Some useful explanations

P.S。 TDateTime是用户类型的错误名称。


2
投票

在桌面版本的Delphi(Windows,OSX)中,操作员重载仅可用于记录。对于移动版本的编译器,ARC表示operator overloading is available for classes

类的运算符重载

使用ARC内存管理的一个非常有趣的副作用是,编译器可以处理函数返回的临时对象的生存期。一种特殊情况是操作员返回的临时对象。实际上,新的Delphi编译器的一项全新功能是能够为类定义运算符,具有自2006年Delphi以来可用于记录的相同语法和模型。

而且,如果我没记错的话,在现已停产的.net编译器中可以使用运算符重载。这再次成为可能,因为.net垃圾收集器可以整理所有临时对象。

上面的文档摘录指出了为什么非ARC版本的类无法进行运算符重载。没有一些自动的生命周期管理,临时类会泄漏。另一方面,可以在堆栈的自动存储中创建和销毁临时记录。

就是说,您在某种程度上被错误命名的类型看起来在任何情况下都可以作为值类型更好。因此,解决您的问题的方法是:

  1. 请给您的类型一个更好的名称,不要与基本类型冲突。
  2. 将类型更改为record,即值类型。

2
投票

作为旁注:

您可以在Delphi .NET编译器(此后已停止使用)中的类上使用它,因为.NET垃圾回收最终将删除操作员返回的新对象实例,最近在基于ARC的Delphi ARM编译器中使用(这也会根据引用计数释放内存)。

回答您的问题:

您不能在不支持ARC的本机Delphi编译器中的类上使用它(当前Windows,OS X和iOS模拟器的基于Intel的x86和x64编译器不支持ARC),因为它会大量泄漏内存,因为运算符将返回没有人释放的新对象实例。

随着ARC(当前基于ARM的移动平台)的引入,您可以像那些编译器一样很好地进行编译。

注意:

  • 小心重新定义现有的Delphi类型,例如TDateTime
  • 请注意,您只能在ARC编译器上使用以下内容,因此您在编写高度依赖于平台的代码
  • 如果您想跨平台,则将其设置为类似于TTimeStamp record的值类型

在下面的代码(仅适用于ARC)中,将class替换为record可以使其跨平台。 .NET框架的TimeSpanDateTime(您可能基于其代码)不是struct引用类型,也不是巧合。

总而言之,在编写跨平台代码时,请注意值和引用类型,并在使用运算符重载时偏爱class值类型。

record
© www.soinside.com 2019 - 2024. All rights reserved.