Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi如何解决带整数参数的重载函数?_Delphi - Fatal编程技术网

Delphi如何解决带整数参数的重载函数?

Delphi如何解决带整数参数的重载函数?,delphi,Delphi,考虑以下计划: program IntegerOverloads; {$APPTYPE CONSOLE} procedure WordOrCardinal(Value: Word); overload; begin Writeln('Word'); end; procedure WordOrCardinal(Value: Cardinal); overload; begin Writeln('Cardinal'); end; procedure SmallintOrInteger(

考虑以下计划:

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
Unsigned variables passed as parameters:
Byte
Word
Cardinal

Signed variables passed as parameters:
Byte
Byte
Byte
在Delphi 6上,我必须删除
UInt64
重载,因为该类型在Delphi 6上不存在。输出为:

Unsigned variables passed as parameters:
Byte
Word
Cardinal
Uint64

Signed variables passed as parameters:
Uint64
Uint64
Uint64
Uint64
Unsigned variables passed as parameters:
Byte
Word
Cardinal

Signed variables passed as parameters:
Byte
Byte
Byte
同样,这两种行为看起来都不符合以下说法:

在这些情况下,如果可以在没有歧义的情况下这样做 编译器使用 容纳调用中实际参数的最小范围


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

Delphi XE输出:

Small
Long
64
64

你如何解释“范围”?如果您将其视为“Word和Smallint都有65536个不同的值”,那么XE2输出与文档匹配。如果您将其视为“Word的范围从0到65535,Smallint的范围从-32768到32767”,那么据我所知,根据您链接到的文档,没有正确的答案。@hvd我的解释是您描述的第二个解释。+1。问得好。起初我认为这与分配给每个变量的不同值有关,但一些实验表明情况并非如此。(给
\u word
分配一个非常小的值不会改变它的大小,而给
SmallInt
分配一个非常大的值也会保持不变。)我想知道这是否与对32/64位支持所做的更改有关?@ken“起初我认为这与分配给每个变量的不同值有关”这引出了一个有趣的话题。数据流分析。Delphi编译器不执行任何操作。如果你写i:=1;如果i>0,编译器将在运行时检查不等式。编译器只是不进行数据流分析。我认为这不是坏事。没有任何批评。事实上,XE2的行为是有意义的;我认为早期版本是错误的。使用32位的
整数
调用
WordOrCardinal
,应该调用
基数
版本,除非有任何关于该值的编译时信息,因为不能假定32位
整数
适合16位
Word
。同样的情况也适用于
ShortintOrSmallInt(_word)
,其中16位
单词
不可能被假定为适合8位
ShortInt
,因此它改为
SmallInt
。它可能会导致运行时范围检查或溢出异常,但是在编译时没有考虑的价值。我遗漏了什么吗?是的,这样做很有意义,将无符号变量传递给接受有符号参数的过程。另一种方法很麻烦。@DavidHeffernan-如果你在写重载,为什么不多写一些(对于有符号的类型)来消除所有歧义?我不是这样写代码的。我认为那是雷区。Jolyon的博客文章让我思考,我想了解编译器为什么会这样做。是的,这是一个雷区,即使编译器工程师解释编译器为什么会这样做,它仍然是一个雷区。