标题: VBS对象作为过程参数是ByVal还是ByRef?
作者: Demon
链接: https://demon.tw/programming/vbs-object-byval-byref.html
版权: 本博客的所有文章,都遵守“署名-非商业性使用-相同方式共享 2.5 中国大陆”协议条款。
有网友在《VBS过程和函数参数传递的方式默认是ByVal还是ByRef?》中回复:
虽然今天才看到您的这篇文章,顺手也回复一下。关于传址和传值的错误确实很误导,完全相反。另外,对于将对象作为过程参数的话,无论指定ByVal与否,都是传址。VBS对于对象变量相当于只保留一个别名。等同于在参数中使用了SET关键词。以前编程需要做了一个由VBS生成对象传递到Excel VBA的过程中的软件,发现这个问题。不知道这个认识是否正确?
遗憾的是,这个认识并不正确,VBS对象作为过程参数的传递方式仍然取决于过程中定义该参数是ByVal还是ByRef。可以用一个简单的例子测试一下:
Dim fso
Set fso = CreateObject("Scripting.FilesyStemObject")
'Author: Demon
'Website: https://demon.tw
'Date: 2015/8/12
'传值
SubByVal fso
WScript.Echo TypeName(fso) '输出FileSystemObject
'传址
SubByRef fso
WScript.Echo TypeName(fso) '输出Nothing
Sub SubByVal(ByVal obj)
Set obj = Nothing
End Sub
Sub SubByRef(ByRef obj)
Set obj = Nothing
End Sub
很容易看出ByVal和ByRef是不一样的,学过C++的人应该不难理解。
VBS对象变量其实类似于C++里的指针,如果是以ByVal的方式传递参数,obj变量是指针的一份拷贝,当将obj指向Nothing的时候,原来的指针fso仍然不变;而如果是以ByRef的方式传递参数,则obj变量相当于fso的别名(也就是指向指针的指针),当将obj指向Nothing的时候,原来的fso指针也指向Nothing。
赞赏
微信赞赏支付宝赞赏
随机文章:
怎么又重提起这个来了?
文章里面写了啊,指出某网友的错误认识。
以指针做类比确实很好的理解其中的意义。对于最后的销毁对象确实没问题,但是如果希望建立对象副本的话就不同了,VBS有没有建立对象副本的机制?看如下例子:
Class objTest
public testmsg
End Class
Sub TestByVal(ByVal obj) ‘设想使用ByVal传值,但并不建立对象副本,而是对象别名,类似Set
obj.testmsg=”From ByVal”
End sub
Sub TestByRef(ByRef obj) ‘ 传址
obj.testmsg=”From Byref”
End Sub
Sub TestByValDestory(ByVal obj)
Set obj=Nothing
End sub
Sub TestByRefDestory(ByRef obj)
Set obj=Nothing
End sub
Dim objArgument
Set objArgument=New objTest
objArgument.testmsg=”No Argument”
TestByVal(objArgument) ‘输出 “From ByVal”
MsgBox objArgument.testmsg
TestByRef(objArgument) ‘输出 “From ByRef”
MsgBox objArgument.testmsg
TestByValDestory objArgument ‘验证了您的结论
MsgBox TypeName(objArgument)
TestByRefDestory objArgument ‘验证了您的结论
MsgBox TypeName(objArgument)
我想我大概明白你的意思了,只不过你之前的表述有些错误,你想表达的是无论指定ByVal与否都不会建立对象副本。VBS并没有提供这样的机制,要创建对象副本的话需要自己动手写拷贝函数。
是的,如果是对象做为参数,不论ByVal还是ByRef,这个对象都不会额外生成一个副本。就算一个Set Nothing了,不会影响别个的指针,但是如果更改了Object的内部值,所有指向该对象的副本也会同时修改。