delphi - 为什么在 'Child' 方法中将参数类型从 'const' 切换到 'var' 时无法传递 'overloaded' 类实例

标签 delphi delphi-10.2-tokyo

MCVE:

在重载方法中将参数类型从const切换到varout时,以下代码编译不会出错TAnimalTrainer

类的训练

但如果未指定则它会编译。

[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.

找到解决方法:

  • 省略var
  • 将局部变量转换为 TAnimal(Dog)
  • 坚持使用const

问题:这是编译器中的错误吗?

最佳答案

Is this a bug in the compiler?

不,不是。

尽管您在重载方法的上下文中发现了这一点,但重载掩盖了真正的问题。如果我们消除过载,就会更容易理解这个问题。

因此,为此,请考虑这个程序:

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.

在调用 GetAnimal 时无法编译,并出现以下错误:

[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));

当你这样做时,程序会编译,但输出是

FALSE

在程序的上下文中,编译器面临一些重载。正如我们在此示例中所看到的,编译器无法接受将 TDog 变量传递给 TAnimal var 参数,因此它会拒绝该重载。它知道它无法将 TDog 变量传递给 string 参数,因此被拒绝。此时,不再有重载方法,因此会出现错误消息。

关于delphi - 为什么在 'Child' 方法中将参数类型从 'const' 切换到 'var' 时无法传递 'overloaded' 类实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55308448/

相关文章:

html - 如何在Delphi中生成一个tinyurl

delphi - 使用 FireDac 仅更新 1 个重复行(无主键或唯一字段)

delphi - FormatSettings.ShortDateFormat 与系统区域设置不同

delphi - 使用 OLE 和 Delphi 提高 Word 文档中搜索替换的性能

Delphi,将字符串复制到字节数组

delphi - 使用虚拟类访问私有(private)字段

sqlite - fireDAC 访问 SQLite 中的表锁

delphi - 为什么编译器无法加载库名dbexpint.dll?

xcode - Delphi:PAServer:获取支持调试的权限...失败

delphi - 小刻度 TeeChart delphi 对数刻度