函数或过程的参数,至少有三种不同的类型(实际不只三种,这里我们只讨论三种)。
1、数值参数(按值传递by val)
数值参数在函数或过程中相当于局部变量,在函数中可以对此变量作修改,并且原始变量保持不变。范例:
program Project1; {$APPTYPE CONSOLE} uses SysUtils; function SquareAndMultiply(Num1, Num2: Integer): Integer; begin Num1 := Num1 * Num1; { 在这里Num1,Num2相当于局部变量} Num2 := Num2 * Num2; Result := Num1 * Num2; end; var X, Y, Z: Integer; begin X := 2; Y := 3; Z := SquareAndMultiply(X, Y); Writeln('SquareAndMultiply(' + IntToStr(X) + ', ' + IntToStr(Y) + ') = ' + IntToStr(Z)); Readln; end.
在SquareAndMultiply调用中,X和Y两个数值传递进去,并且在内部对两个数值进行了平方处理。但在Writeln输出中X和Y的值没有发生改变。结果如下图:
当函数用数值参数时,编译器首先为传递给函数的变量制作一个拷贝,并把拷贝送给函数,原始变量不变就是因为传递给函数的是拷贝而不是实际变量。
2、常量参数
如果不想使传递给函数或过程的参数发生改变,就用const关键字来声明参数。
范例如下:
program Project1; {$APPTYPE CONSOLE} { 用关键字const声明的Astr字符串参数} procedure SaySomething(const Astr: string); begin Astr := Astr + 'Test'; { Ctrl+F9编译会报错} Writeln(Astr); end; begin SaySomething('Hello, World'); Readln; end.
当我们用Ctrl+F9来编译该段代码时,会报错,如下:
产生错误的原因是因为关键字const使得变量Astr不能修改,任何企图修改常量参数都会产生编译器错误。
Tip
参数const不仅保护了变量的值不被改变,而且对于传递给函数或过程的字符串和记录来说能产生更优化的代码。
3、引用参数
引用参数和数值参数不同,编译器不会为传递进去的参数制作一个拷贝,而直接传递实际参数(实参),这就意味着,在函数或过程中,对变量的任何修改都会改变原始变量。
以1、数值参数的范例进行改写如下:
program Project1; {$APPTYPE CONSOLE} uses SysUtils; { 用关键字var声明引用参数} function SquareAndMultiply(var Num1, Num2: Integer): Integer; begin Num1 := Num1 * Num1; { 在这里Num1,Num2相当于引用的实参} Num2 := Num2 * Num2; Result := Num1 * Num2; end; var X, Y, Z: Integer; begin X := 2; Y := 3; Z := SquareAndMultiply(X, Y); Writeln('SquareAndMultiply(' + IntToStr(X) + ', ' + IntToStr(Y) + ') = ' + IntToStr(Z)); Readln; end.
我们注意一下SquareAndMultiply函数的参数,都是由关键字var来声明的。
我们来看看运行结果和1、数值参数中的结果有什么不同吧,如下图:
我们看到给函数SquareAndMultiply传递进去的X和Y变量已经不是原来的2和3了,变成了4和9。
Tip
函数只能返回一个值,但是通过引用参数,可以取得一个函数多值返回的效果。函数仍然只能返回一个值,但是通过引用传递使得传递的参数得以改变,从效果上来看,这样函数返回了多个值。
以上代码均在Delphi7中测试通过。