1. Forward 声明(前置声明)
当使用一个标识符(任何类型)时,编译器必须已经知道该标识符指的是什么。为此,你通常需要在例程使用之前提供一个完整的声明。然而在某些情况下可能做不到这一点,例如过程A调用过程B,而过程B又调用过程A,那么你写过程代码时,不得不调用编译器尚未看到其声明的例程。
欲声明一个过程或函数,而且只给出它的名字和参数,不列出其实现代码,需要在句尾加forward 关键字:
procedure Hello; forward;
该代码例子没有实际意义,仅仅是为帮助理解概念
procedure DoubleHello; forward;
procedure Hello;
begin
if MessageDlg ('Do you want a double message?',
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
DoubleHello
else
ShowMessage ('Hello');
end;
procedure DoubleHello;
begin
Hello;
Hello;
end;
尽管 forward 过程声明在Delphi中不常见,但是有一个类似的情况却经常出现。当你在一个单元(关于单元的更多内容见下一章)的interface 部分声明一个过程或一个函数时,它被认为是一个forward声明,即使没有forward关键字也一样。实际上你不可能把整个例程的代码放在interface 部分,不过你必须在同一单元中提供所声明例程的实现。
类内部的方法声明也同样是forward声明,当你给窗体或其组件添加事件时, Delphi会自动产生相应的代码。在TForm 类中声明的事件是forward 声明,事件代码放在单元的实现部分。
2. 函数重载
重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同。实际上,编译器是通过检测参数来确定需要调用的例程。
声明重载函数有两条原则:
每个例程声明后面必须添加overload 关键字。
例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。
示例代码
procedure ShowMsg (str: string); overload;
begin
MessageDlg (str, mtInformation, [mbOK], 0);
end;
procedure ShowMsg (FormatStr: string;
Params: array of const); overload;
begin
MessageDlg (Format (FormatStr, Params),
mtInformation, [mbOK], 0);
end;
procedure ShowMsg (I: Integer; Str: string); overload;
begin
ShowMsg (IntToStr (I) + ' ' + Str);
end;
三个过程分别用三种不同的方法格式化字符串,然后在信息框中显示字符串。下面是三个例程的调用:
ShowMsg ('Hello');
ShowMsg ('Total = %d.', [100]);
ShowMsg (10, 'MBytes'
3. 返回值
需要注意的是在Delphi中没有类似其他语言的return关键字,如果必须想实现return的效果需要使用result 和exit 联合使用
声明带有返回值函数的格式
function 函数标示符(参数列表):返回值;
3.1. 通过引用传递数据
传递数据的默认值是按值调用的。从字面上看,参数值被传递给子例程参数。然后参照变量值的这个副本。
按引用传递意味着子例程实际上是指传入的变量而不是其值。对值的任何更改都会影响调用者变量。我们声明一个变量,通过var前缀引用来传递。
这种方式在不提供例程输出具体代码的情况下也会改变传入的变量值
procedure DoIt(Var A : Integer);
begin
A := A * 2;
ShowMessageFmt('A in the procedure = %d',[A]);
end;
3.2. 仅输出参数
procedure DoIt(Out A : Integer);
begin
A := 123;
ShowMessageFmt('A in the procedure = %d',[A]);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
A : Integer;
begin
ShowMessage('A before the call is unknown');
// Call the procedure
DoIt(A);
ShowMessageFmt('A in program now = %d',[A]);
end;
3.3. 通过Result和者函数名
Result是函数特有的局部变量,它的类型与函数的返回类型相同,对它的赋值等于对函数名赋值。与函数名不同,Result变量可以出现在赋值号的右边,如果函数名出现在赋值号的右边时,则意味着递归调用,也就是函数调用它自己。
function MyFunc(s:Integer):Integer;
Begin
//执行赋值但不返回。
Result:=Result*s;
//赋值后程序返回。
MyFunc:=s*s;
End;
function MyFunc():Integer;
Begin
Result:=Result+5; //如果使用MyFunc():=MyFunc()+5;将导致死循环。
End;