Board logo

标题: [技术讨论] 我对VBS函数与过程的理解,不对之处请指证 [打印本页]

作者: yiwuyun    时间: 2014-12-31 19:31     标题: 我对VBS函数与过程的理解,不对之处请指证

  1. Option Explicit
  2. dim obj
  3. '只有0个或一个参数时,不论怎样调用都正确。但有两个或以上参数时,加()必须使用call。不使用call,必须去掉()。参数
  4. '之间都用逗号(,)分隔。---过程调用的用法。
  5. call Main("1","2")
  6. 'Main "1","2"
  7. Sub Main(first,second)
  8. For Each obj in ShellObject(1,2).Environment("system")
  9.   WScript.Echo(""+first+":"+second+":"+obj)
  10.   Exit For
  11. Next
  12. End Sub
  13. '函数有三种调用方式。一种是通常用的赋值。一种是过程调用方式,就如上面的Main过程调用一样。第三种如上面,它不赋值,但要用值。
  14. '第一种要保留值,如果值是对象,要用Set obj=Nothing释放;第二种不返回值。第三种不保留值,如果是对象,不需要释放。
  15. Function ShellObject(first,second)
  16.   Set ShellObject= WScript.CreateObject("Wscript.Shell")
  17. End Function
复制代码
请指出不正确之处,如果都对,那不是过程纯粹可以不要了。
作者: g495326    时间: 2015-1-1 12:41

本帖最后由 g495326 于 2015-1-1 13:33 编辑

回复 1# yiwuyun

1.函数和过程的调用方式如下:   
━┉┉┉┉┉┉┉∞┉┉┉┉┉┉┉┉∞┉┉┉┉┉┉┉━


2.对象的返回可以用你说的那种方式,但是会产生2次对象复制操作,浪费时间,我认为最好的方式为在以引用的方式在参数中返回。

3.关于上图错误的调用方式,比如fun(argument, argument)的方式调用并不用产生错误,具体的表现如下
━┉┉┉┉┉┉┉∞┉┉┉┉┉┉┉┉∞┉┉┉┉┉┉┉━


4.使用function完全可以在功能上替换sub。这是没错的,开销方面就不是很清楚了。
作者: yiwuyun    时间: 2015-1-1 13:16

不错,没想到函数和过程对引用有影响。但是对象和非对象的返回好像有点不同吧,对象的返回好像只返回引用吧。非对象的返回才会赋值吧。要不然,对象的赋值何必多此一举,加个Set.我是这样理解的,不晓得对不对。
作者: g495326    时间: 2015-1-1 13:29

回复 3# yiwuyun


    在函数中创建的对象在函数退出后,其对象已经被销毁,如果不发生复制,函数返回的对象将无法调用。
作者: yiwuyun    时间: 2015-1-1 13:38

我试了一下,不是是否加括号的问题,是你是用函数调用还是过程调用的方式,如果是过程调用,引用会起作用,如果是函数调用,就会传值。如果把这一句AppendSuffix(strWord),改成call AppendSuffix(strWord),这时就和AppendSuffix strWord一样了。
作者: yiwuyun    时间: 2015-1-1 13:45

回复 4# g495326
不是说,对象的引用为0时,对象才会消毁吗。如果有引用存在,对象是不会自行消毁的。
作者: g495326    时间: 2015-1-1 14:04

回复 5# yiwuyun


    关于这一点,我是说明的是错误的调用方法产生的二义性,而不是正确的调用方法。
作者: g495326    时间: 2015-1-1 14:12

回复 6# yiwuyun


这是没错,关键对象创建的位置决定了其生命周期,而不是是否为0,在C++中如果一个对象销毁,指向该对象的指针就变成了垂悬指针,会导致内存泄露。

在返回对象时,假设为返回引用,这在C++中函数内创建的对象会延迟销毁,但这种方法被认为不可取(这句话不是我说的)

函数作为独立代码块应做到与外部无关性。
作者: yiwuyun    时间: 2015-1-1 14:24

回复 8# g495326
我们调用的对象都是别人用某种语言写好了的,如果内存泄露,也是那个组件有问题吧。如果在VBS中出现内存泄露,那是没有使用Set obj=Nothing的原因。我现在还不能确信的是这一句会不会出现内存泄露:For Each obj in ShellObject(1,2).Environment("System")。我在想既然VBS允许这种写法,那它应该会自行消毁对象吧。只是没有确切的证据表明这一点。一般在VBS退出之后,即使没有Set obj=Nothing,对象也会消毁吧。我想内存泄露只是针对大的VBS而言吧。那些VBS会一直在内存中运行,它建立的对象又很多,如果不消毁它建立的对象,内存就会越来越小,最后导致系统崩溃。
作者: g495326    时间: 2015-1-1 14:34

回复 9# yiwuyun


关于这种方式返回对象是否会发生对象复制,或者使用了对象延迟销毁对于简短的vbs确实无关紧要。

如果您知道win api函数如何返回,我想您应该懂得我的意思。

虽然我认为这是不好方法,但这种方法确实可以实现对象的返回。
作者: yiwuyun    时间: 2015-1-1 17:25

我认为VBS是不会自己创建对象的。因此根本不存在对象复制的问题,对象都是COM+自己创建的,对象的消毁也都是COM+自己完成的。VBS和COM+之间就是客户和服务器之间的关系。VBS告诉COM+我要用一个对象,你给我建一个,然后COM+把这个对象的引用,其实也就一个地址,告诉VBS,VBS把这个地址赋给自己空间中的变量。如果手动Set obj=Nothing,就是在告诉VBS,我不要这个引用了,VBS就告诉COM+,你把引用计数减1吧。com+如果侦测到自己某个对象的引用计数为0了,就会自己消毁这个对象。因此当VBS完全退出的时候,它会告诉相应的COM+对象把所有的引用计数减下去。这就是我说的你不手动Set obj=Nothing,对象还是会消毁。但是如果对大型的长时期(比如一年)运行很多对象数量的VBS来说,你如果不手动消毁,就叫内存泄露了。VBS就是一个解释器,或者是一个中间人,代理人。
作者: g495326    时间: 2015-1-1 19:51

回复 11# yiwuyun


com是类的封装,以dll形式存在的动态链接库文件,而不是什么对象管理器,对于您的理解不敢苟同。

不知您学习vbs多久了,希望能交个朋友。
作者: yiwuyun    时间: 2015-1-2 09:43

VBS也有自己的类对象,那些类对象就是由VBS创建的,但用CreateObject()方法创建的对象,就是由COM+创建的,如果你看过VC++ COM/COM+编程应该就能明白了。另外C++是不存在延迟消毁对象一说的,C++都是手动消毁对象,只有JAVA才延迟消毁对象,JAVA的程序员从来都是只建对象,不消毁对象,对象是由JAVA垃圾清理器自动完成的。所以JAVA从来不会出现内存泄露。内存泄露是C/C++才会出现的。这只是我个人的理解。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2