为什么在不同单元中调用具有相同签名的函数不会导致编译器错误?

Why doesn't calling a function with identical signatures in different units result in compiler error?

为什么这段代码不会导致编译器错误?我会预料到错误,例如 'ambiguous call to "CallMe"'。这是编译器或语言中的错误吗?这可以通过在函数调用前使用单元名称和一个点来解决,但这不能保护用户代码和库代码免受名称冲突。您认为您的代码做了一些事情,但它做了其他事情,这很糟糕。

uses
  Unit2, Unit3;

{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(CallMe(5)));
end;

unit Unit2;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils;
function CallMe(A: Integer) : Integer;
implementation
function CallMe(A: Integer) : Integer;
begin
  Result := A * 2;
end;
end.

unit Unit3;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils;
function CallMe(A: Integer) : Integer;
implementation
function CallMe(A: Integer) : Integer;
begin
  Result := A * -1;
end;
end.

来自documentation

If two units declare a variable, constant, type, procedure, or function with the same name, the compiler uses the one from the unit listed last in the uses clause. (To access the identifier from the other unit, you would have to add a qualifier: UnitName.Identifier.)

正如设计所说,编译器使用基于堆栈的方法从单元加载符号,并从上次加载到首次加载通过堆栈进行解析以搜索符号。预处理器状态直接合并到全局状态中。

跨单元重载是个例外。如果用 overload; 指令标记两个函数,则会出现错误(bla 是测试中函数的名称)

[dcc32 Error] test.dpr: E2251 Ambiguous overloaded call to 'bla'
  Unit1.pas(8): Related method: procedure bla;
  Unit2.pas(8): Related method: procedure bla;

如果您有两个不同的签名,它将select最匹配的一个。

交叉重载是一项较新的功能,但我不记得确切的时间。我猜是D2006.