具有重载功能的编译器错误

Mat*_*tej 7 delphi overload-resolution delphi-xe5

以下代码给出了堆栈溢出:

function Func(x : Double) : Double; overload;
function Func(x : Integer) : Double; overload;


function Func(x : Double) : Double;
begin
  Result := Func(Round(x));
end;


function Func(x : Integer) : Double;
begin
  Result := 1.0;
end;
Run Code Online (Sandbox Code Playgroud)

Integer重载函数不会被调用时,Double重载函数调用自身,直到堆栈溢出。

以下代码按预期工作:

function Func2(x : Double) : Double; overload;
function Func2(x : Integer) : Double; overload;

function Func2(x : Double) : Double;
var
  ix : Integer;
begin
  ix := Round(x);
  Result := Func(ix);
end;


function Func2(x : Integer) : Double;
begin
  Result := 1.0;
end;
Run Code Online (Sandbox Code Playgroud)

这是编译器错误还是预期的行为?

And*_*and 7

我怀疑这是可以预料的。

问题在于,本机编译器Round函数返回64位整数。CodeInsight和官方文档都告诉我。而且,如果编译器必须在采用32位整数或双精度数的例程之间进行选择,则在给定64位整数时,它会选择接受双精度数的例程。

要验证这一点,请尝试

procedure Test(x: Double); overload;
begin
  ShowMessage('double');
end;

procedure Test(x: Integer); overload;
begin
  ShowMessage('integer');
end;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Test(Int64.MaxValue)
end;
Run Code Online (Sandbox Code Playgroud)


Fab*_*zio 6

System.Round函数产生一个Int64值。

我认为,编译器保留了Double你的过载Func功能超过了拨款Integer超载。

实际上,Integer如果参数的值超过Integer类型的min-max(从-2147483648到2147483647,请参阅System.Integer),则重载可能会导致信息丢失。

Integer参数更改为参数Int64将解决问题并避免信息丢失。

function Func(x : Double) : Double; overload;
function Func(x : Int64) : Double; overload;

...

function Func(x : Double) : Double;
begin
  Result := Func(Round(x));
end;

function Func(x : Int64) : Double;
begin
  Result := 1.0;
end;
Run Code Online (Sandbox Code Playgroud)