重载函数时不接受数组类型参数

Pan*_*mon 6 delphi overloading

在 Delphi 中,我可以这样做:

Type
  TFourCC = Array[0..3] of AnsiChar;

Function Func(Param : TFourCC) : Boolean;
begin
  { ... }
end;

Func('ABCD'); // I can pass this as literal text without problems
Run Code Online (Sandbox Code Playgroud)

现在,我想将此参数设为可选。

Function Func(Param : TFourCC = 'ABCD') : Boolean;
begin
  { ... }
end;
Run Code Online (Sandbox Code Playgroud)

现在,编译器向我抛出一个错误: E2268 Parameters of this type cannot have default values

好的,所以我在想重载函数应该可以解决问题......

Function Func : Boolean; overload;
begin
  { ... }
end;

Function Func(Param : TFourCC) : Boolean; overload;
begin
  { ... }
end;

Func('ABCD'); // This line that worked in first example now gives an error
Run Code Online (Sandbox Code Playgroud)

不幸的是,Delphi 也不喜欢这样。在它首先接受参数作为TFourCC类型变量的地方,它现在给了我E2250 There is no overloaded version of 'Func' that can be called with these arguments.

我不同意这个错误告诉我的,当它没有超载时,同样的事情会起作用。

有人可以向我解释这背后的逻辑,以及可能的解决方案吗?我想保持TFourCC原样(不是字符串类型),这样可以更轻松地处理读取和写入。我宁愿避免在传递它之前先将它分配给一个变量,因为该函数将被大量使用..

And*_*and 6

不幸的是,这就是当前类型系统的工作方式。

但好消息是,您可以使用记录和运算符重载来变魔术。例如,与

type
  TFourCC = record
  strict private
    function GetChar(Index: Integer): AnsiChar;
    procedure SetChar(Index: Integer; const Value: AnsiChar);
  public
    class operator Implicit(AValue: AnsiString): TFourCC;
    class operator Implicit(AValue: TFourCC): AnsiString;
    class operator Equal(a, b: TFourCC): Boolean;
    class operator NotEqual(a, b: TFourCC): Boolean;
    property Chars[Index: Integer]: AnsiChar read GetChar write SetChar; default;
  case Boolean of
    False: (AnsiChars: array[0..3] of AnsiChar);
    True: (Data: Cardinal)
  end;

implementation

{ TFourCC }

class operator TFourCC.Implicit(AValue: AnsiString): TFourCC;
begin
  if Length(AValue) <> 4 then
    raise Exception.Create('Not a valid TFourCC string.');
  Result.Data := PCardinal(@AValue[1])^;
end;

class operator TFourCC.Implicit(AValue: TFourCC): AnsiString;
begin
  SetLength(Result, 4);
  PCardinal(@Result[1])^ := AValue.Data;
end;

class operator TFourCC.Equal(a, b: TFourCC): Boolean;
begin
  Result := a.Data = b.Data;
end;

class operator TFourCC.NotEqual(a, b: TFourCC): Boolean;
begin
  Result := a.Data <> b.Data;
end;

function TFourCC.GetChar(Index: Integer): AnsiChar;
begin
  Result := AnsiChars[Index];
end;

procedure TFourCC.SetChar(Index: Integer; const Value: AnsiChar);
begin
  AnsiChars[Index] := Value;
end;
Run Code Online (Sandbox Code Playgroud)

您将获得所有这些好处:

procedure TForm1.FormCreate(Sender: TObject);
var
  x: TFourCC;
begin
  x := 'FINE';                     // implicit conversion from string
  ShowMessage(x);                  // implicit conversion to string
  x[0] := 'D';                     // can access parts for writing (without explicit member)
  ShowMessage(x);
  ShowMessage(x[0]);               // can access parts for reading (without explicit member)
  ShowMessage(x.Data.ToString);    // can access underlying storage as a 32-bit integer
end;
Run Code Online (Sandbox Code Playgroud)

而且,你现在可以做

procedure TForm1.FormCreate(Sender: TObject);
var
  x: TFourCC;
begin
  x := 'FINE';                     // implicit conversion from string
  ShowMessage(x);                  // implicit conversion to string
  x[0] := 'D';                     // can access parts for writing (without explicit member)
  ShowMessage(x);
  ShowMessage(x[0]);               // can access parts for reading (without explicit member)
  ShowMessage(x.Data.ToString);    // can access underlying storage as a 32-bit integer
end;
Run Code Online (Sandbox Code Playgroud)

不幸的是,我现在着急,所以我现在不能仔细检查正确性或进一步评论!