今天我们聊聊在过程中参数的两种传递方式。 按值传递:ByVal 将参数值而不是将地址传递给过程的方式,这就使在过程中访问的只是变量的副本。 在过程中修改参数值的时候,其实修改的只是变量的副本的值,从而不会改变变量的真正值。 这里说到的地址,真正值,复本,可能把大家给绕晕了,看个例子。 Sub Main() Dim a As Long Dim b As Long a= 1: b = 2 MsgBox prompt:="a=" & a & ",b=" & b,Title:="调用过程前" Call ByVal1(a, b) MsgBox prompt:="a=" & a & ",b=" & b,Title:="调用过程后" End Sub Sub ByVal1(ByVal a As Long, ByVal b AsLong) MsgBox prompt:="修改a的值=100,b的值等于100", Title:="按值传递" a= 100 b= 100 End Sub 在sub过程Main里声明了a和b两个长整型变量,a赋值1,b赋值2。 在调用Sub过程ByVal1之前,先通过消息框显示a和b的当前值。 在sub过程ByVal1的声明里,通过使用ByVal 关键字,两个参数都是按值传递。 在ByVal1过程内修改参数的变量值前先照例通过消息框显示参数变量的值。 修改完后参数变量的值后,返回到Main过程里继续执行CALL下面的语句。 这里的难点,就在于理解按值传递时,实际上传递的只是一个复本。 理论是枯燥的,但是通过代码,大家兴许可以明白些。 在被调用的过程中,参数变量的值该过程中修改后,在过程结束返回后,相关的变量值没有改变。 按地址传递:ByRef 将参数地址而不是将值传递给过程的方式,在过程中访问到实际的变量。 所以在过程中对参数变量的赋值,都会变量的真正值。 除非另作说明,否则按地址传递参数。 我们看个例子。 Sub Main() Dim a As Long Dim b As Long a= 1: b = 2 MsgBox prompt:="a=" & a & ",b=" & b,Title:="调用过程前" Call ByRef1(a, b) MsgBox prompt:="a=" & a & ",b=" & b,Title:="调用过程后" End Sub Sub ByRef1(ByRef a As Long, ByRef b AsLong) MsgBox prompt:="修改a的值=100,b的值等于100", Title:="按地址传递" a= 100 b= 100 End Sub 由于不做说明的情况下,均是按址传递,所以上面的声明Sub ByRef1(ByRef a As Long, ByRef b As Long)也可以改成Sub ByRef1(aAs Long, b As Long)。 另外,在按址传递参数的方式下,传递一个常量值作为参数,即使修改了参数变量的值,也是不会保留的。 例如 Call ByRef1(1,2) 额外知识点: A.用户定义类型不能以ByVal的方式传递。 B.数组中个别的元素可以按ByVal传递,但整个数组必须以ByRef传递。 可以传递括号中的数组参数,或是将它放在 Variant 之中,再将此 Variant 传递至ByVal 参数。 示例: Sub test() Dim a As Variant Dim b() b= Range("a1:c3").Value a= b Call arr(a) End Sub Sub arr(ByVal a) a(1, 1) = 1 a(2, 1) = "a" a(3, 1) = True End Sub
|
|