delphi - 重载运算符和转换类型

标签 delphi delphi-xe2

我有一个关于使用运算符重载进行类型转换的问题,这里有一个完整的示例代码:

program OVerloads;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TMyRange = record
  private type
    TMyRangeEnum = 1 .. 90;
  var
    FMyRangeEnum: TMyRangeEnum;
  public
    class operator Implicit(const Value: Integer): TMyRange;
    class operator Implicit(const Value: TMyRange): Integer;
    class operator Explicit(const Value: Integer): TMyRange;
    class operator Explicit(const Value: TMyRange): Integer;
  end;

class operator TMyRange.Implicit(const Value: Integer): TMyRange;
begin
    Result.FMyRangeEnum := Value;
end;

class operator TMyRange.Implicit(const Value: TMyRange): Integer;
begin
  Result := Value.FMyRangeEnum;
end;

class operator TMyRange.Explicit(const Value: Integer): TMyRange;
begin
  Result.FMyRangeEnum := Value;
end;

class operator TMyRange.Explicit(const Value: TMyRange): Integer;
begin
  Result := Value.FMyRangeEnum;
end;

var
 MyValue: TMyRange;
 MyVar: TMyRange; // (or Integer, not change nothing)
 MyArr: array[1..90] of TMyRange; // (or Integer, not change nothing) 
begin
  try
    { TODO -oUser -cConsole Main : Insert code here }

    MyValue := 90;
    Writeln(MyValue);  // [1] Not work, error: E2054 Illegal in Write/Writeln statement

    Writeln(Integer(MyValue));  // Work

    MyVar := MyArr[MyValue];   // Not work, error: E2010 Incompatible types: 'Integer' and 'TMyRange'                

    MyVar := MyArr[Integer(MyValue)];  // work      

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

可能我忘记了一些东西,但是我可以解决 mnode 中的问题 [1],不需要一直显式 Integer(myValue) ? 再次感谢,非常感谢。

最佳答案

你似乎把这个问题过于复杂化了。定义一个范围类型,如下所示:

type
  TMyRange = 1..90;

然后像这样声明你的数组:

var
  MyArr: array[TMyRange] of TMyRange;

就是这样。

<小时/>

无论出于何种原因,您断言需要在此处使用带有运算符重载的记录。尽管如此,但您几乎已经确定,运算符重载隐式转换不能用于强制您的类型与 Writeln 和整数数组索引兼容。我找不到任何描述这些场景的文档,但很明显编译器不会让你做你想做的事。

据我所知,您可以依赖实际参数的隐式转换和赋值语句的右侧。

这是我演示选项的最小示例:

program Overloads;
{$APPTYPE CONSOLE}
type
  TRec = record
  private
    function GetOrd: Integer;
  public
    class operator Implicit(const Value: TRec): Integer;
    property ord: Integer read GetOrd;
  end;

class operator TRec.Implicit(const Value: TRec): Integer;
begin
  Result := 0;
end;

function TRec.GetOrd: Integer;
begin
  Result := 0;
end;

procedure Foo(i: Integer);
begin
end;

var
  R: TRec;
  a: array[0..0] of Integer;

begin
  Writeln(R);//E2054 Illegal type in Write/Writeln statement
  Writeln(Integer(R));//explicit cast, provided by class operator Implicit
  Writeln(R.ord);//my preferred option, a property
  a[R] := 0;//E2010 Incompatible types: 'Integer' and 'TRec'
  a[Integer(R)] := 0;//again, explicit cast is fine
  a[R.ord] := 0;//or using a property
  Foo(R);//implicit cast used for actual parameters
end.

注释:

  1. 如果您提供隐式强制转换运算符,则无需同时提供显式强制转换运算符。显式强制转换将导致隐式运算符被调用。
  2. 我认为记录类型的属性比显式转换产生的代码更具可读性。

关于delphi - 重载运算符和转换类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9546433/

相关文章:

delphi - 如何创建自己的非系统剪贴板?

delphi - 在列表框 Canvas 上绘制 unicode 文本太慢

web-services - WebService使用的释放变量

Delphi:如何为自定义组件创建额外的设计时菜单?

使用泛型的 Delphi 属性 getter 函数

xml - 释放时 TXMLDocument 'Invalid pointer operation'

delphi - 当 Delphi 处于覆盖模式时,如何改变它的光标形状?

delphi - :=什么时候不能作为赋值运算符工作?

delphi - 如何分析 Delphi DLL 文件中的转储文件?

delphi - 如何从Windows获取用于存储缓存缩略图的永久目录?