我有一个关于使用运算符重载进行类型转换的问题,这里有一个完整的示例代码:
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.
注释:
- 如果您提供隐式强制转换运算符,则无需同时提供显式强制转换运算符。显式强制转换将导致隐式运算符被调用。
- 我认为记录类型的属性比显式转换产生的代码更具可读性。
关于delphi - 重载运算符和转换类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9546433/