Почему вызов функции с одинаковыми сигнатурами в разных единицах не приводит к ошибке компилятора?

Почему этот код не приводит к ошибке компилятора? Я бы ожидал ошибку, например, "неоднозначный вызов"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.

2 ответа

Решение

Из документации:

Если два модуля объявляют переменную, константу, тип, процедуру или функцию с одинаковым именем, компилятор использует тот из модуля, который указан последним в предложении использования. (Чтобы получить доступ к идентификатору из другого модуля, вам необходимо добавить квалификатор: UnitName.Identifier.)

Как уже было сказано, компилятор загружает символы из модулей с использованием подхода, основанного на стеке, и анализирует стек от последней загруженной к первой загруженной для поиска символа. Хотя состояние препроцессора напрямую объединено с глобальным состоянием.

Перегрузка между узлами является исключением, хотя. Если вы пометите обе функции с перегрузкой; директива, вы получаете ошибку (бла было названием функции в тесте)

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

если у вас есть две разные подписи, он выберет самую подходящую.

перекрестная перегрузка - более новая функция, но я точно не помню, когда. Я думаю, D2006.

Другие вопросы по тегам