delphi参数传递
参数传递
声明/实现一个过程使用的参数称为形式参数(简称形参),调用过程时传入的参数称为实际参数(简称实参)。
{ Info是形参}
procedure ShowInfo(Info: String);
begin
ShowMessage(Info);
end;
var
S: String;
begin
S := 'lxpbuaa';
{S是实参}
ShowInfo(S);
end;
参数传递分两种:按值(by val)和引用(by ref)。这两种方式的本质区别是:
按值传递时,形参和实参是两个变量,它们开始时的值是相同的,即实参的数据被拷贝一份传递给了形参。所以此时,形参的改变不会影响到实参。
引用传递时,形参和实参是同一个变量,可以将它们之一看做是另一个的别名。 所以此时,形参改变时,实参跟着改变。
默认情况下,参数是按值传递的,传递的是数据拷贝;如果加了var前缀,则成了引用传递。
我们看如下例子:
procedure TForm1.ByVal(I: Integer); {按值传递I}
begin
ShowMessage(IntToStr(Integer(@I)));
{取得形参所在地址。你会发现它和实参地址是不同的,因为此时实参和形参是不同的两个变量}
I := I + 1;
end;
procedure TForm1.ByRef(var I: Integer); {引用传递I}
begin
ShowMessage(IntToStr(Integer(@I)));
{取得形参所在地址。你会发现它和实参地址是相同的,因为此时实参和形参是同一个变量}
I := I + 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
I := 1;
ShowMessage(IntToStr(Integer(@I))); {取得实参所在地址}
ByVal(I); { I =1}
Showmessage(i); {i:=1;实参没有变}
ByRef(I); { I =2}
showmessage(i); {i:=2,实参改变了}
end;
按值传递的参数可以指定默认值,比如上面的ByVal可以是这样:
procedure ByVal(I: Integer = 0);
调用它时可以省掉有默认值的参数:ByVal。带默认值的参数必须位于参数
列表的最后,如:
procedure ByVal(I: Integer = 0; B: Boolean);
是不行的,应该改为:
procedure ByVal(B: Boolean; I: Integer = 0);
因为默认值必须是一个常数表达式,所以dynamic-array、procedural、class、class-reference和interface等参数只能指定nil默认值;而record、variant、file和static-array等类型的参数则根本不能指定默认值。
如果按值传递一个指针类型的参数,情况会变得复杂而又很有意思。此时,实际传递的是什么呢?是实际数据的拷贝吗?不,是指针的拷贝,也就是说形参和实参是两个指针,不过这两个指针指向了相同地址。所以这时候,形参和实参可以共享它们指向地址中的数据,但如果改变了形参的指针指向,实参的指针指向不能跟着改变。那么总结一下,就是:按值传递指针参数时,实参和形参可以共享指针指向地址中的数据,但是不能共享指针本身的
指向。而引用传递时,因为实参和形参是同一个变量,因此实现完全共享。看下面的例子:
procedure TForm1.ByVal(Obj: TObject);
begin
Obj := Button1;
{改变形参指针指向,实参的指针指向不会跟着改变,因为它们是两个变量。如果仅仅是改变Obj的属性而不改变指向,则实参的属性会跟着改变}
end;
procedure TForm1.ByRef(var Obj: TObject);
begin
Obj := Button1;
{改变形参指针指向,实参的指针指向跟着改变,因为它们是同一个变量}
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TObject;
begin
Obj := Self;
{Self即Form1,所以此时实参Obj的类名(ClassName)是"TForm1"}
ByVal(Obj); {按值传递指针变量Obj}
ShowMessage(Obj.ClassName); {显示类名"TForm1"}
ByRef(Obj); {引用传递指针变量Obj}
ShowMessage(Obj.ClassName); {显示类名"TButton1"}
end;
上面讲了这么多,最根本的还是一句话:按值传递时,形参和实参是两个变量;引用传递时,形参和实参是同一个变量。抓住这句话,就等于抓住了一