MCVE:
The following code does not compile with error when switching the parameter type from const
to var
or out
in the overloaded method Train
of the class TAnimalTrainer
but it compiles if non is specified.
[dcc32 Error] Project14.dpr(41): E2250 There is no overloaded version of 'Train' that can be called with these arguments
program Project14;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TAnimal = class
private
FName: string;
end;
TDog = class(TAnimal)
public
constructor Create(Name: string);
end;
TAnimalTrainer = record // class or record
public
procedure Train({const}var aA: TAnimal); overload; // class method or not
procedure Train(const aName: string); overload;
end;
{ TAnimalTrainer }
procedure TAnimalTrainer.Train(const aName: string);
var
Dog: TDog;
begin
Dog := nil;
try
Dog := TDog.Create(aName);
Train(Dog); // error here
finally
Dog.Free;
end;
end;
procedure TAnimalTrainer.Train(var aA: TAnimal);
begin
aA := nil;
end;
{ TDog }
constructor TDog.Create(Name: string);
begin
FName := Name;
end;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Found workarounds:
var
.TAnimal(Dog)
const
.Question: Is this a bug in the compiler?
Is this a bug in the compiler?
No it is not.
Although you have discovered this in the context of an overloaded method, the overloading is disguising the real problem. It will be much easier to understand the issue if we remove the overload.
So, to that end, consider this program:
type
TAnimal = class
end;
TDog = class(TAnimal)
end;
procedure GetAnimal(var AAnimal: TAnimal);
begin
AAnimal := TAnimal.Create;
end;
var
Dog: TDog;
begin
GetAnimal(Dog);
end.
This fails to compile in the call to GetAnimal
with this error:
[dcc32 Error]: E2033 Types of actual and formal var parameters must be identical
Why does the compiler reject this? Well, imagine if it accepted this. If it did so then when GetAnimal
returned the Dog
variable would refer to an object that was not a TDog
.
To see this, change the body of the program to look like this:
GetAnimal(TAnimal(Dog));
Writeln(Dog.InheritsFrom(TDog));
When you do so, the program compiles, but the output is
FALSE
In the context of your program, the compiler is faced with some overloads. As we have seen in this example, the compiler cannot accept passing a TDog
variable to a TAnimal
var parameter, so it rejects that overload. It knows that it cannot pass a TDog
variable to a string
parameter, so that is rejected. At which point, there are no overloaded methods left, hence the error message.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With