VBS对象作为过程参数是ByVal还是ByRef?

标签: , , , , , ,

有网友在《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。

 

赞赏

微信赞赏支付宝赞赏

随机文章:

  1. VC编写在Windows 7下需要管理员权限的程序
  2. VBS中的Microsoft.CmdLib对象
  3. OpenTextFile与Unicode
  4. 一个VBS恶作剧程序的解密
  5. 在Windows下源码编译PHP

5 条评论 发表在“VBS对象作为过程参数是ByVal还是ByRef?”上

  1. Jorkin说道:

    怎么又重提起这个来了?

    • Demon说道:

      文章里面写了啊,指出某网友的错误认识。

      • Mark Andersen说道:

        以指针做类比确实很好的理解其中的意义。对于最后的销毁对象确实没问题,但是如果希望建立对象副本的话就不同了,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)

        • Demon说道:

          我想我大概明白你的意思了,只不过你之前的表述有些错误,你想表达的是无论指定ByVal与否都不会建立对象副本。VBS并没有提供这样的机制,要创建对象副本的话需要自己动手写拷贝函数。

  2. Jorkin说道:

    是的,如果是对象做为参数,不论ByVal还是ByRef,这个对象都不会额外生成一个副本。就算一个Set Nothing了,不会影响别个的指针,但是如果更改了Object的内部值,所有指向该对象的副本也会同时修改。

留下回复