如何重载简单的整数Delphi函数?

时间:2012-11-17 23:24:30

标签: delphi types overloading

使用Delphi 7,我有几个函数接受一个整数参数。这些函数对属于该对象的Text字符串进行操作。唯一的参数是Text中的字符索引或单词索引。例如,要在单词i之后或在我想要的字符Text [loc]之后检索文本的下一个单词:

function NextWord(i:Integer): String; overload;
function NextWord(loc:Integer): String; overload;

显然,这是模棱两可的。 Delphi帮助说“重载例程必须通过它们采用的参数数量或参数类型来区分。”所以我定义了两种类型:

type WordIndex = Integer;
type CharIndex = Integer;
...
function NextWord(i:WordIndex): String; overload;
function NextWord(i:CharIndex): String; overload;

但这不起作用,因为它们只是Integer的别名。

Delphi对类型的帮助区分了“类型标识”,“类型兼容性”和“赋值兼容性”,然后没有说明如何使用区别。但它确实说重复“类型”这个词来创建与Integer不同的新类型:

type WordIndex = type Integer;    //really, a new type
type CharIndex = type Integer;
...
function NextWord(i:WordIndex): String; overload;
function NextWord(i:CharIndex): String; overload;
...
var WordNumber: WordIndex;      //variable of new type
...
  WordStr := NextWord(WordNumber);  //call overloaded function

令我惊讶的是,这也不起作用。编译器将WordIndex识别为单独的类型,并编译重载的函数,但在调用它声称重载是不明确的。我也尝试将函数参数更改为VAR(因为“对于var参数,正式和实际的类型必须相同。”),但这没有帮助。

点击Web我读到编译器首先根据参数的数量消除重载函数的歧义,然后根据它们的大小消除歧义。我想我可以使WordIndex成为DWord而不是Integer,但我不希望它是16位,而我使用-1来表示“无效字数”。

最后,我在“重载过程和函数”的帮助中找到了这个:“你可以传递一个重载的例程参数,这些参数的类型与任何例程的声明中的参数不同,但它们与赋值兼容多个声明中的参数....在这些情况下,当没有歧义时可以这样做时,编译器会调用其参数属于范围最小的类型的例程,该范围适应调用中的实际参数。

所以我尝试了这个,有效:

type WordIndex = -1..High(Integer);
type CharIndex =  Integer;
function NextWord(i:WordIndex): String; overload;
function NextWord(i:CharIndex): String; overload;
...
var WordNumber: WordIndex;
    loc: CharIndex;
...
  WordStr := NextWord(WordNumber);
  (or)
  WordStr := NextWord(loc);

这样编译时没有警告或错误,实际上为每个参数类型调用了正确的函数。 SizeOf(WordIndex)= SizeOf(CharIndex)= 4.I.E。他们都是整数。

我的问题是,这是我应该这样做的方式吗?如果是这样,我怎么知道呢?在“帮助”或“来源”中是否有类似的例子?

奖金问题:我检查了,并且使类型为WordIndex的Range在调用或函数中不会产生代码/运行时开销。但是它可能在代码的其他地方吗? Delphi是否会在任何不测试整数的情况下测试WordNumber的范围错误? (我很确定答案是'不'。)

2 个答案:

答案 0 :(得分:5)

尝试在这里使用重载只会导致痛苦和痛苦。想象一下当你想使用整数文字时会发生什么?或者想象你想要传递一个表达式的索引NextWord,例如A + B。或者传递函数的返回值。您是否会拥有返回您建议定义的各种专用类型的函数?想想任何必须阅读代码的人。他们将如何确定调用哪个重载?

你可以通过赋予你的功能不同的名字来避免所有的痛苦。当您有多个带有不同类型参数的函数时,重载是合适的。这里情况不同。您的函数采用相同类型的参数。所以你的功能需要不同的名字。

组织它的另一种方法是使用单个函数,但要将更多函数传递给函数。传递索引和枚举类型,该类型描述如何解释该索引。您可以将这两个值组合成一个记录。

答案 1 :(得分:1)

如果遇到此类问题,请使用重构来分隔不同的行为。例如,您可以按位置和char索引拆分单词提取,您可以引入两个新类:

电话会是:

MyClass.Location.NextWord(SomeIndex);
MyClass.Character.NextWord(SomeIndex);

另一种方法可能是使用第二个参数提供方法:

MyClass.NextWord(SomeWordIndex, wmiByWordLocation);
MyClass.NextWord(SomeCharIndex, wmiByCharLocation);

但是,我建议重构。