Delphi函数中参数的使用实例|方法|技巧
参数
函数定义时参数列表中的参数称为形参,函数调用时参数列表中的参数称为实参。在定义的函数原型中,多个参数之间用分号隔开,同一类型的参数可以放在一起,以逗号隔开。函数调用的时候,在函数原型中,多个参数之间用逗号隔开。
一般来说,形参列表和实参列表完全匹配是指参数的个数一样,而且顺序排列的数据类型也完全一致。对于普通的函数,如果编译器发现实参的数据类型与形参的数据类型不匹配,会将实参的数据类型进行一次或多次的“提升”,比如把Integer 类型转换为Double 类型。可以为过程和函数的参数指定默认数值。
指定默认数值的参数要放在参数列表的后部,而没有指定默认数值的参数要放在参数列表的前部。在函数调用的时候,可以为设置了默认值的参数指定一个新值。在函数体中,各语句使用的是指定的新值,如果没有指定新值,则使用默认值。同样,如果存在多个设置了默认值的参数,只有在前面的参数指定了新值后,后面的参数才可以指定新值。
下面的例子定义了一个OutputNum 函数,可以将一个浮点数按指定的精度输出。通过这个例子,
读者可以体会函数中参数的使用:
program Project1;
{$APPTYPE CONSOLE}
uses Sysutils; //为了使用函数Format
function OutputNum(number:double;n:integer = 5):Boolean;
var
Str : string; //浮点数显示输出的内容
begin
if n <= -1 then //小数点后的位数要大于或等于0
begin
Result:=False;
Exit; //退出显示函数
end
else
begin
// 设置显示的格式
Str := Format(’%*.*f’, [10, n, number]);
Result := True ;
Writeln(Str); //显示数据
end;
end;
begin
OutputNum(12.345); //n 默认为5
OutputNum(123,3); //参数对数据类型进行升级
//下面一句代码不正确,故屏蔽掉
//OutputNum(123.456789,9.13); //参数对数据类型不能降级
//可以根据函数的返回值确定下一步的操作
if OutputNum(123.456789,-3) = False then
Writeln( ’输出失败。’ ) ;
Readln;
end.
运行结果如下:
12.34500
123.000
输出失败。
这里有几点需要说明:
• 为了使用函数Format,需要在Uses 语句中将Sysutils 单元包含进去。
• 由于小数点后的位数不可以设置为负数,所以当出现负数时,OutputNum 函数返回False,并调用Exit 函数立刻退出OutputNum 函数。
• 在语句OutputNum(123,3)中,首先将整型常数123 转换为浮点型常数,然后进行参数传递。
最常用的参数有3 种,分别为数值参数、变量参数和常量参数。
数值参数在运行过程中只改变其形参的值,不改变其实参的值,即参数的值不能传递到过程的外面。试看下面的例程:
procedure Calculate(CalNo:Integer);
begin
CalNo := CalNo*10;
end;
用以下例程调用Calculate 函数:
Calculate(Number);
Number 进入Calculate 函数后,会把Number 实参拷贝给形参CalNo,在此过程中CalNo 增大10倍,但并未传递出来,所以说Number 值并未改变。形参和实参占用不同的内存地址,在过程或函数被调用时,将实参的值复制到形参占用的内存中。因此,在跳出过程或函数后,形参和实参的数值是不同的,但实参的值并不发生变化。
如果想改变传入的参数值,就需要使用变量参数,即在被调用程序的参数表中的形参前加上保留字Var。例如:
procedure Calculate(var CalNo : Integer);
则CalNo 并不在内存中占据一个位置,而是指向实参Number。当一个实参被传递时,任何对形参所作的改变都会反映到实参中,这是因为两个参数指向同一个地址。将上一个例程中的形参CalNo前面加上Var,再以同样的程序调用它,则在第2 个编辑框中会显示计算的结果,把第1 个编辑框中的数值放大10 倍。这时形参CalNo 和实参Number 的值都是Nnmber 初始值的10 倍。
如果过程或函数执行时要求不改变形参的值,最有保证的办法是使用常量参数。在参数表的参数名称前加上保留字Const 就可以使一个形参成为常量参数。使用常量参数代替数值参数可以保护用户的参数,使用户在不想改变参数值时不会意外地将新的值赋给这个参数。下面的例子可以帮助读者加深理解:
program Project1;
{$APPTYPE CONSOLE}
type
PInteger = ^Integer; //定义指针类型
procedure P1(var N:Integer); //引用参数传递
begin
N:=N+1 ;
end;
procedure P2(N:Integer); //普通参数传递
begin
N:=N+2;
end;
procedure P3(PT:PInteger); //传递指针参数
begin
PT^:=PT^+3;
end;
var
i:Integer;
begin
i:=1;
P1(i); //将i 的值增加1
Writeln(’i:’,i);
P2(i); //希望将i 加2,但没有实现
Writeln(’i:’,i);
P3(@i); //将i 加3
Writeln(’i:’,i);
Readln;
end.
运行结果如下:
i:2
i:2
i:5
这里有几点需要说明:
• 一开始变量i 的数值为1,经过P1 过程的处理,将i 加1,所以显示的第1 个i 的数值为2,这时使用的是引用参数传递。
• 在过程P2 中,将形参的数值增加了2,实际上i 并没有增加,所以显示的第2 个i 的数值仍然为2。在这种情况下,正常的做法可以使用函数的返回值,例如:
Result:=N+2;
在调用函数的时候使用:
i:=P2(i);
• 在过程P3 中,传递的是变量I 的指针,所以操作是针对i 进行的,第3 次显示i 的数值是5。