Array-typisierter Parameter wird bei Überladungsfunktion nicht akzeptiert
In Delphi kann ich das tun:
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
Jetzt möchte ich diesen Parameter optional machen.
Function Func(Param : TFourCC = 'ABCD') : Boolean;
begin
{ ... }
end;
Jetzt wirft mir der Compiler einen Fehler: E2268 Parameters of this type cannot have default values
Ok, also dachte ich, eine Überladung der Funktion sollte dann den Trick machen ...
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
Leider mag Delphi das auch nicht. Wo es den Parameter zuerst als TFourCCtypisierte Variable akzeptiert hat , gibt es mir jetzt E2250 There is no overloaded version of 'Func' that can be called with these arguments.
Ich bin nicht einverstanden mit dem, was mir dieser Fehler sagt. Dasselbe hat funktioniert, wenn es nicht überladen war.
Kann mir jemand die Logik dahinter erklären und möglicherweise eine Lösung? Ich möchte das so lassen, TFourCCwie es ist (kein String-Typ), es erleichtert das Lesen und Schreiben erheblich. Ich vermeide es lieber, es zuerst einer Variablen zuzuweisen, bevor ich es übergebe, da die Funktion häufig verwendet wird .
Antworten
Leider funktioniert das Typsystem derzeit so.
Aber die gute Nachricht ist, dass Sie mit Aufzeichnungen und Überladung von Operatoren zaubern können. Zum Beispiel mit
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;
Sie erhalten alle diese Vorteile:
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;
Und das können Sie jetzt tun
procedure f(A: TFourCC); overload;
begin
ShowMessage(A);
end;
procedure f; overload;
begin
ShowMessage('ABCD');
end;
Leider habe ich es gerade sehr eilig, daher kann ich die Richtigkeit oder den Kommentar im Moment nicht noch einmal überprüfen!