《VB程序设计》第四章第四节 参数的传递.docx
《《VB程序设计》第四章第四节 参数的传递.docx》由会员分享,可在线阅读,更多相关《《VB程序设计》第四章第四节 参数的传递.docx(13页珍藏版)》请在冰点文库上搜索。
《VB程序设计》第四章第四节参数的传递
《VB程序设计》第四章第四节 参数的传递
最后修改:
2010-6-223:
16:
59
第四节 参数的传递
参数是在本过程有效的局部变量,用于传递信息。
在调用一个有参数的过程时,首先进行的是“形参和实参结合”,实现调用过程的实参与被调过程的形参之间的数据传递,数据传递有两种方式:
按值传递和按地址传递。
例如,下面实例由于传递的参数个数不匹配而出错。
PrivateFunctionDivisor(ByValxAsString,ByValyAsInteger)
′函数Divisor计算最大公约数
…
EndFunction
Divisor有两个参数,而调用语句中形参个数只有一个,代码如下:
PrivateSubForm_Click()
DimmAsInteger,nAsInteger,EAsInteger
N=InputBox("请输入N")
M=InputBox("请输入M")
g=Divisor(n)′未提供m参数
Printn;"和";m;"的最大公约数是:
";g
EndSub
单击窗体运行程序时,则会显示出错信息,如图4-4-1所示。
图4-4-1
一、形参和实参
1.形参
在被调用过程中的形参,出现在Sub过程和Function过程中。
在过程被调用之前,形参并未被分配内存,只是说明形参的类型和在过程中的作用。
形参列表中的各参数之间用逗号(,)分隔,形参可以是变量名和数组名,定长字符串变量除外。
2.实参
实参是在主调过程中的参数,在过程调用时实参将数据传递给形参。
形参列表和实参列表中的对应变量名可以不同,但实参和形参的个数、顺序以及数据类型必须相同。
因为“形实结合”是按照位置结合,即第一个实参与第一个形参结合,第二个实参与第二个形参结合,依此类推。
例如,在求最大公约数的[例Ex_Divisor1]中被调用函数和调用过程如下:
PrivateFunctionDivisor(ByValxAsInteger,ByValyAsInteger)
EndSub
PrivateSubForm_Click()
G=Divisor(n,m)
EndSub
当运行单击窗体事件调用Divisor过程时,首先进行“形实结合”。
形参与实参的结合对应关系是:
n→>x,m→y。
3.形参的数据类型
在创建过程时,如果没有声明形参的数据类型,则默认为Variant型。
例如,将[例Ex_Divisor1]函数过程中的x为Variant型,y为Integer型:
PrivateFunctionDivisor(ByValx,ByValyAsInteger)
EndFunction
对于实参数据类型与形参定义的数据类型不一致时,VB会按要求对实参进行数据类型转换,然后将转换值传递给形参。
例如,将[例Ex_Divisor1]函数的实参n的数据类型改为Single型,被调函数如下:
PrivateSubForm_Click()
DimnAsSingle,mAsInteger,gAsInteger
N=InputBox(″请输入N″)
M=InputBox(″请输入M″)
G=Divisor(n,m)
Printn;″和″;m;″的最大公约数是:
″;g
EndSub
被调函数过程如下:
PrivateFunctionDivisor(ByValxAsInteger,ByValyAsInteger)
EndSub
运行上述程序,当从InputBox输入框中输入n为44.5,m为25。
当执行“g=Divisor(n,m)”语句时,先将Single型的n转换成44(Integer),然后将44→x,25→y.运行结果为:
44.5和25的最大公约数是:
1
4.使用可选的参数
参数列表中的参数可以是可选的,在参数表中含有Optional关键字的参数是可选的。
如果某一参数为可选参数,则参数表中此参数后面的其他参数也必须是可选的,并要用Optional来声明。
例如,[例Ex_Divisor1]的被调函数定义修改为:
PrivateFunctionDivisor(OptionalxAsIntege,OptionalyAsInteger)
在Form_Click事件过程中,程序代码如下:
g=Divisor(n)′未提供第二个参数
g=Divisor(,n)′未提供第一个参数
在未提供可选参数时,实际上是将该参数作为具有Variant型的Empty来赋值。
不过,在本程序中如果将m或n作为Empty,在Divisor函数中的mod运算时会出错。
二、参数按值传递和按地址传递
在VB中传递参数有两种方式:
按值传递(PassedByValue)和按地址传递(PassedByReference),其中按地址传递习惯上称为“引用”。
1.按值传递参数
按值传递使用ByVal关键字。
按值传递参数时,VB给传递的形参分配一个临时的内存单元,将实参的值传递到这个临时单元去。
实参向形参传递是单向的,如果在被调用的过程中改变了形参值,则只是临时单元的值变动,不会影响实参变量本身,当被调过程结束返回主调过程时,VB将释放形参的临时内存单元。
[例Ex_Max]用函数过程编写求a、b两数中最大数。
Max函数为求最大数,在cmdStart_Click事件中调用Max函数,程序代码如下:
OptionExplicit
PrivateFunctionmax(ByValxAsInteger,ByValyAsInteger)
DimzAsInteger
Ifx z=x
x=y
y=z
EndIf
max=x
Text4.Text=x
Text5.Text=y
EndFunction
PrivateSubCommand1_Click()
DimaAsInteger,bAsInteger,cAsInteger
a=Val(Text1.Text)
b=Val(Text2.Text)
Text3.Text=max(a,b)
Text6.Text=a
Text7.Text=b
EndSub
当在文本框txtA和txtB中输入变量a为7,b为8时,数据的传递过程如下:
通过函数调用,给形参分配:
临时内存单元x和y,将实参a和b的数据传递给形参。
在被调函数中x、y和z交换数据,调用结束实参单元a和b仍保留原值,参数的传递是单向的。
运行结果界面如图4-4-2所示,被调函数Max中的x和y已经交换过了,分别为8和7,而主调函数中的a和b仍为7和8。
图4-4-2
2.按地址传递参数
在定义过程时,如果没有ByVal关键字,默认的是按地址传递参数,或者用Byref关键字指定按地址传递。
按地址传递参数,是指把形参变量的内存传递给被调用过程,形参和实参具有相同的地址,即:
形参、实参共享同一段存储单元。
因此,在被调过程中改变形参的值,则相应实参的值也被改变,也就是说,与按值传递参数不同,按地址传递参数可以在被调过程中改变实参的值。
将[例Ex_Max]求两数中最大数的程序按值传递改为按地址传递,程序代码如下:
OptionExplicit
PrivateFunctionmax(xAsInteger,yAsInteger)
DimzAsInteger
Ifx z=x
x=y
y=z
EndIf
max=x
Text4.Text=x
Text5.Text=y
EndFunction
PrivateSubCommand1_Click()
DimaAsInteger,bAsInteger,cAsInteger
a=Val(Text1.Text)
b=Val(Text2.Text)
Text3.Text=max(a,b)
Text6.Text=a
Text7.Text=b
EndSub
由于形参和实参共用同一内存单元,因此在被调函数中交换x和y的数值后,a和b的数值也同榉发生变化。
运行结果如图4-4-3所示,a和b的数据也交换了。
图4-4-3
按地址传递参数比按值传递参数更节省内存空间,程序的运行效率更高。
对于按地址传递的形参,如果在过程调用时与之结合的实参是常数或表达式,则VB会用按值传递的方法处理,给形参数分配一个临时的内存单元,将常数或表达式传递到这个临时的内存单元去。
[例Ex_MulSum]计算5!
+4!
+3!
+2!
+1!
,按照按地址参数传递的方法编写程序,代码如下:
PrivateFunctionmultiply(nAsInteger)
multiply=1
DoWhilen>0
multiply=multiply*n
n=n-1
Loop
EndFunction
PrivateSubForm_Click()
DimsumAsInteger,iAsInteger
Fori=5To1Step-1
sum=sum+multiply(i)
Next
Print"sum=";sum
EndSub
运行结果:
Sum=120
120而不是希望的153,本程序只计算了5!
=120。
因为,形参n是按地址传递的,在第一次调用Multiply函数后n的值为o,由于实参与形参共享地址单元,实参i的值也是0。
当执行“Sum=Sum+Multiply(i)”语句后,Sum的值是120,执行“Next”语句后在判断语句“Fori:
5To1Step-1时就退出For循环。
因此For循环只执行了一次,求了5!
的值。
解决办法:
·将函数定义改为按值传递:
PrivateFunctionMultiply(ByValnAsInteger)AsInteger
·将实参i改为表达式,因为表达式是按值传递的。
把变量改为表达式的最简单的方法是用()将变量括起来。
调用语句为:
Sum=Sum十Multiply((i))
三、数组参数
在定义过程时,数组可以作为形参出现在过程的形参列表中。
声明数组参数的语法如下:
语法:
形参数组名()[As数据类型]
形参数组对应的实参必须也是数组,数据类型与形参一致,实参列表中的数组不需要用“()”。
过程传递数组只能按地址传递,形参与实参共有同一段内存单元。
在被调过程中不能用Dim语句对形参数组声明,否则会产生“重复声明”的编译错误。
但是在使用动态数组时,可以用Redim语句改变形参数组的维界,重新定义数组的大小。
当返回调用过程时,对应的实参数组的维界也跟随发生变化。
[例Ex_AverScore]用同一个函数Average求正式员工和临时员工的的平均工资。
运行结果的界面如图4-4-4所示。
图4-4-4
程序代码如下:
OptionExplicit
PrivateFunctionaverage(stuarray()AsSingle,nAsInteger)_AsSingle
'求平均值
DimiAsInteger
DimaverAsSingle,sumAsSingle
Fori=1Ton-1
sum=sum+stuarray(i)
Next
aver=sum/n
average=aver
EndFunction
PrivateSubcmdstart_Click()
Dimsalary1(5)AsSingle,salary2(8)AsSingle
salary1(0)=1900:
salary1
(1)=1970:
salary1
(2)=1915
'设置初始值
salary1(3)=1600:
salary1(4)=1655
salary2(0)=2675:
salary2
(1)=2780:
salary2
(2)=2715
salary2(3)=2540:
salary2(4)=2990:
salary2(5)=2770
salary2(6)=2895:
salary2(7)=2765
'求正式员工工资
Text1.Text=Int(average(salary2(),8)*100)/100
'求临时员工工资
Text2.Text=Int(average(salary1(),5)*100)/100
EndSub
程序分析:
·被调函数Average的数据类型为Single型。
·为了使同一个函数Average,在调用过程Form_Click事件中将数组的元素个数作为参数传递,然后通过Redim语句重新定义数组的大小,使Average函数具有通用性。
因此,对于数组元素个数不定的函数、可以采用将元素个数作为参数传递的方法。
·程序中的“Int(Average(Salaryl(),5)*100)/100”是为了显示时取两位数。
四、对象参数
在VB中对象也可以作为形参,即对象可以向过程传递,对象的传递只能是按地址传递。
对象作为形参时形参变量的类型声明为“Control”,或声明为控件类型,例如,形参类型声明为“Label”或“Form”,则表示可以向过程传递标签控件或窗体。
[例Ex_FormArgul]创建一个人员管理系统。
在窗体frmFirst中创建了3个按钮,3个按钮组成按钮数组,不同按钮的Caption属性值不同,单击不同的按钮进入窗体frmSecond。
窗体frmFirst和窗体frmSecond中的控件属性如表4-4-1所示。
表4-4-1
对 象
控件名
属性名
属性值
Form
frmFirst
Caption
人员管理
Command
cmdEmp
Index
Caption
正式员工
cmdEmp
Index
Caption
退休员工
cmdEmp
Index
Caption
临时员工
Label
labEmplo
Index
0
Caption
正式在册的员工信息
labEmplo
Index
1
Caption
退休的员工信息
labEmplo
Index
2
Caption
临时的员工信息
Form
frmSecon
Caption
空
Label
Label1
Caption
空
为了使系统简单化,系统设计为在窗体frmFirst中单击不同按钮都打开同一个窗体frmSecond,但frmSecond显示不同的标题和标签内容,窗体frmSecond的标题和标签内容是通过过程参数传递的,如图4-4-5(a)是运行时窗体frmFirst,图4-4-5(b)是当单击按钮“正式员工”cmdEmployee(0)时的窗体frmSecond的显示情况。
(a)
(b)
图4-4-5
采用将窗体和标签作为参数,通过按钮的不同索引值(index)传递按钮的“caption”属性给形式参数,使单击不同的按钮打开的窗体上显示不同的窗体标题和标签。
程序代码如下:
PrivateSubfrmselect(fAsForm,cmdcapAsString)
'传递窗体参数
f.Caption=cmdcap&"人员管理"
EndSub
'传递窗体参数
PrivateSublabselect(lAsControl,cmdcapAsString)
l.Caption="欢迎进入"&Chr(13)&cmdcap&"人员管理"
l.FontSize=16
l.FontBold=True
l.Visible=True
frmsecond.Show
frmfirst.Hide
EndSub
PrivateSubcmdemployee_click(indexAsInteger)
'单击不同按钮
'将按钮的文本传递给frmsecond窗体标题
Callfrmselect(frmsecond,cmdemployee(index).Caption)
Calllabselect(frmsecond.Label1,cmdemployee(index).Caption)
frmsecond.Show
frmfirst.Hide
EndSub
程序分析:
在SubfrmSelect函数中以窗体为形参,定义为“FAsForm”;在SublabSelect函数中以标签为形参,定义为“LAsLabel”。