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

时间:2014-03-20 18:25:07

标签: delphi syntax operator-overloading

我在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;

错误发生在第4行

E2123预期的程序,功能,财产或VAR

我为Windows写这个。但是,如果它仅适用于.net和iOS,我该如何为Windows执行此操作?

3 个答案:

答案 0 :(得分:11)

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

Some useful explanations

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

答案 1 :(得分:2)

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

  

类的运算符重载

     

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

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

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

那就是说,你的错误命名类型在任何情况下都可能更适合作为值类型。因此,您的问题的解决方案是:

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

答案 2 :(得分:2)

作为旁注:

您可以在Delphi .NET编译器中使用它(从那时起已停止使用),因为.NET垃圾收集最终将删除运算符返回的新对象实例,最近基于ARC的Delphi ARM编译器(也根据引用计数释放内存)。

回答你的问题:

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

随着ARC(目前基于ARM的移动平台)的推出,你可以像编译器那样编译好。

注意:

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

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

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

type
  TTimeSpan = class
    Ticks: Longint;
  end;

  TDateTime = class
  public
    Ticks: Longint;
    class operator Add(a: TDateTime; b: TTimeSpan): TDateTime;
    class operator Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
    constructor Create(aTicks: Longint);
  end;

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

constructor TDateTime.Create(aTicks: Integer);
begin
  Ticks := aTicks;
end;

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