21

考虑以下程序:

program IntegerOverloads;
{$APPTYPE CONSOLE}

procedure WordOrCardinal(Value: Word); overload;
begin
  Writeln('Word');
end;

procedure WordOrCardinal(Value: Cardinal); overload;
begin
  Writeln('Cardinal');
end;

procedure SmallintOrInteger(Value: Smallint); overload;
begin
  Writeln('Smallint');
end;

procedure SmallintOrInteger(Value: Integer); overload;
begin
  Writeln('Integer');
end;

procedure ShortintOrSmallint(Value: Shortint); overload;
begin
  Writeln('Shortint');
end;

procedure ShortintOrSmallint(Value: Smallint); overload;
begin
  Writeln('Smallint');
end;

procedure Main;
var
  _integer: Integer;
  _cardinal: Cardinal;
  _word: Word;
begin
  WordOrCardinal(_Integer);
  SmallintOrInteger(_cardinal);
  ShortintOrSmallint(_word);
end;

begin
  Main;
  Readln;
end.

XE2编译时的输出为:

Cardinal
Integer
Smallint

Delphi 6编译时的输出为:

Word
Smallint
Shortint

文档状态(强调我的):

您可以将类型与任何例程声明中的参数不同但与多个声明中的参数赋值兼容的参数传递给重载例程。当例程使用不同的整数类型或不同的实数类型重载时,这种情况最常发生 - 例如:

procedure Store(X: Longint); overload;
procedure Store(X: Shortint); overload;

在这些情况下,如果可以毫无歧义地这样做,编译器会调用例程,其参数的类型具有容纳调用中的实际参数的最小范围

但这似乎适用于此。示例代码中的所有过程调用都不接受容纳调用中实际参数的类型。

我找不到任何描述编译器遵循什么规则的文档。谁能指出我这样的文件?

这个问题是由以下文章提出的:


更新

在 Ken White 评论的提示下,我编写了另一个程序来说明更多的奇怪之处:

program IntegerOverloadsPart2;
{$APPTYPE CONSOLE}

procedure Test(Value: Byte); overload;
begin
  Writeln('Byte');
end;

procedure Test(Value: Word); overload;
begin
  Writeln('Word');
end;

procedure Test(Value: Cardinal); overload;
begin
  Writeln('Cardinal');
end;

procedure Test(Value: Uint64); overload;
begin
  Writeln('Uint64');
end;

procedure Main;
var
  _byte: Byte;
  _shortint: Shortint;
  _word: Word;
  _smallint: Smallint;
  _cardinal: Cardinal;
  _integer: Integer;
  _uint64: UInt64;
  _int64: Int64;
begin
  Writeln('Unsigned variables passed as parameters:');
  Test(_byte);
  Test(_word);
  Test(_cardinal);
  Test(_uint64);
  Writeln;
  Writeln('Signed variables passed as parameters:');
  Test(_shortint);
  Test(_smallint);
  Test(_integer);
  Test(_int64);
end;

begin
  Main;
  Readln;
end.

当由 XE2 编译时,输出为:

Unsigned variables passed as parameters:
Byte
Word
Cardinal
Uint64

Signed variables passed as parameters:
Uint64
Uint64
Uint64
Uint64

在 Delphi 6 上,我必须删除UInt64重载,因为 Delphi 6 上不存在该类型,输出为:

Unsigned variables passed as parameters:
Byte
Word
Cardinal

Signed variables passed as parameters:
Byte
Byte
Byte

同样,这两种行为看起来都与以下陈述一致:

在这些情况下,如果可以毫无歧义地这样做,编译器会调用例程,其参数的类型具有容纳调用中的实际参数的最小范围

4

1 回答 1

2

无符号类型都不能容纳有符号类型;引用的文档与您的示例一致 - 它只是没有说明编译器将如何处理它们。另一方面,有符号类型可以容纳无符号类型(SmallInt 容纳 Byte,LongInt 容纳 Word,Int64 容纳 Cardinal):

program IntegerOverloadsPart3;
{$APPTYPE CONSOLE}

procedure Test(Value: ShortInt); overload;
begin
  Writeln('Short');
end;

procedure Test(Value: SmallInt); overload;
begin
  Writeln('Small');
end;

procedure Test(Value: LongInt); overload;
begin
  Writeln('Long');
end;

procedure Test(Value: Int64); overload;
begin
  Writeln('64');
end;

procedure Main;
var
  _byte: Byte;
  _word: Word;
  _cardinal: Cardinal;
  _uint64: UInt64;
begin
  Writeln('Unsigned variables passed as parameters:');
  Test(_byte);
  Test(_word);
  Test(_cardinal);
  Test(_uint64);
  Writeln;
end;

begin
  Main;
  Readln;
end.

德尔福 XE 输出:

Small
Long
64
64
于 2012-09-22T19:24:38.517 回答