重载函数时不接受数组类型参数
Array typed parameter not accepted when overloading function
在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
现在,我想将此参数设为可选。
Function Func(Param : TFourCC = 'ABCD') : Boolean;
begin
{ ... }
end;
现在,编译器向我抛出一个错误: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
不幸的是,Delphi 也不喜欢这样。它首先接受参数作为 TFourCC
类型变量,现在它给了我 E2250 There is no overloaded version of 'Func' that can be called with these arguments
.
我不同意这个错误告诉我的内容,同样的事情在它没有超载时也有效。
有人可以向我解释这背后的逻辑,以及可能的解决方案吗?我想保持 TFourCC
原样(不是字符串类型),这样可以更轻松地处理读写。我宁愿避免在传递它之前先将其分配给变量,因为该函数将被使用 alot..
不幸的是,这就是当前类型系统的工作方式。
但好消息是您可以对记录和运算符重载施展魔法。例如,
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;
您将获得所有这些好处:
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;
而且,您现在可以做到
procedure f(A: TFourCC); overload;
begin
ShowMessage(A);
end;
procedure f; overload;
begin
ShowMessage('ABCD');
end;
不幸的是,我现在非常很匆忙,所以我现在不能double-check正确性或进一步评论!
在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
现在,我想将此参数设为可选。
Function Func(Param : TFourCC = 'ABCD') : Boolean;
begin
{ ... }
end;
现在,编译器向我抛出一个错误: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
不幸的是,Delphi 也不喜欢这样。它首先接受参数作为 TFourCC
类型变量,现在它给了我 E2250 There is no overloaded version of 'Func' that can be called with these arguments
.
我不同意这个错误告诉我的内容,同样的事情在它没有超载时也有效。
有人可以向我解释这背后的逻辑,以及可能的解决方案吗?我想保持 TFourCC
原样(不是字符串类型),这样可以更轻松地处理读写。我宁愿避免在传递它之前先将其分配给变量,因为该函数将被使用 alot..
不幸的是,这就是当前类型系统的工作方式。
但好消息是您可以对记录和运算符重载施展魔法。例如,
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;
您将获得所有这些好处:
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;
而且,您现在可以做到
procedure f(A: TFourCC); overload;
begin
ShowMessage(A);
end;
procedure f; overload;
begin
ShowMessage('ABCD');
end;
不幸的是,我现在非常很匆忙,所以我现在不能double-check正确性或进一步评论!