Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 9964|回复: 18

[已解决]关于定义对象变量时何时用new关键字等若干问题?

  [复制链接]
发表于 2011-3-22 09:25 | 显示全部楼层 |阅读模式
本帖最后由 Saint_Zuo 于 2011-3-22 09:26 编辑

1、运行附件中模块1的atest没问题,但运行btest报错,请教在btest中能否加入set语句使得运行成功呢,如果能又该怎么写?另外在vba定义对象变量时候究竟何时该用new,何时又不必用呢,如果不用是否一定要用set为变量赋值呢?
2、在myclass类模块中的ByRef Cancel As Boolean中的byref关键字的含义是什么,以前只看到过By与ByVal呀。
3、(1)Public Property Get Value() As String
      Value = s
      End Property
     (2)Public Property Let Value(ByVal c As String)
      s = c
    End Property

以上两个过程在类模块中是否必须成对出现的?为什么在这里去掉(2)可运行atest,而去掉(1)运行就报错呢?
最佳答案
2011-3-24 18:27
第一问:什么是类模块?类模块是一个封装好的,虚拟化的模块!就像一个文本框,在VBA语言内部,已经有一个类模块,专门处理文本框的各种属性和事件,方法。我们在表格或者窗体中添加一个文本框,就是建立了一个文本框类模块的一个实例。于是这个文本框就具有了长,宽,name等属性。在没有画这个文本框之前,那你说“有一个文本框,它的长是多少?宽是多少?”所以我们自己建立的类模块,也就是打造一个虚拟的模块,拥有某些属性,拥有某些方法。我们要使用我们的类模块,dim xx as myclass这个只是建立了一个对myclass类的一个引用,但并未实例化,也就是说我们现在拥有了一个变量,这个变量用来表示我们的类,但这个类的实例依然不存在。那么接着 set xx = new myclass,这个就是建立一个全新的myclass实例,这个实例才拥有类myclass的初始化属性(intilialize)。


第二问和第三问为自己的理解,建议查阅相关的"New 与 Nothing 关系"相关的资料。查看官方解释。
第二问,得理解set mc= nothing,这里的Nothing是什么意思?在VBA语言中,set xx = Nothing,这里的Nothing 关键字主要用于取消对象变量mc与实际对象的关联,消除mc对实例对象的引用。set mc=nothing不是说mc变量什么也不是了,mc依然是你定义的myclass。只是mc前面所代表的实例对象被消除了。例如:
sub Testing()
  dim mc as myclass
  set mc = new myclass
  mc.Value = "huhuhuhu"
  set mc = Nothing
  set mc = New myclass
  mc.Value = "xxxx"
  msgbox mc.value
End sub
这个实例可以看出,set mc = Nothing是消除的Value叫做huhuhuhu对象的实例。但并不影响变量mc的继续使用。mc本身并不会被消除。
dim mc as myclass,那么mc在消除引用后,则还原为myclass状态;
dim  mc as new myclass,那么mc在消除对象后,则还原为new Myclass状态。

第三问:dim mc as new myclass定义的mc变量为局部变量,将随着过程的结束而消失。虽然前面利用set mc = nothing消除了实例对象的引用,但mc变量并没有消除,他依然表示一个new myclass,他的内存空间依然未释放。所以end sub会触发析构函数事件。那么可能疑问dim mc as myclass呢?看一个实例:
Sub bTest()
Dim mc As myclass
Set mc = New myclass
Debug.Print mc.Value
'Set mc = Nothing  '通过注销这一句代码可以验证mc在什么时候被消除了!
MsgBox "DFxxx" 'Debug.Print mc.Value '会出错
End Sub
'析构函数改成如下:
Private Sub Class_Terminate()
s = "def"
End Sub

变量定义问题.rar

5.77 KB, 下载次数: 9

 楼主| 发表于 2011-3-22 10:35 | 显示全部楼层
回复

使用道具 举报

发表于 2011-3-22 11:06 | 显示全部楼层
New实际上是对象实例化,为对象分配内存,所以,没有实例化的都要New
Sub bTest()
    Dim mc As myclass
    Set mc = New myclass
    Debug.Print mc.Value
End Sub



类模块中的两个并不一定要成对出现,一个是读属性,一个是写属性.实际情况有的属性是只读的
回复

使用道具 举报

 楼主| 发表于 2011-3-23 10:51 | 显示全部楼层
回复 吕?布 的帖子

多谢了,还有一个问题想请教您。
如果在myclass类模块中加入
Private Sub Class_Terminate()
s = "def"
End Sub
那么如何在标准模块中写入程序查看当Class_Terminate事件发生时 Value的值变为"def"。

我在标准模块中写入
Sub bTest()
Dim mc As myclass
Set mc = New myclass
Debug.Print mc.Value
Set mc = Nothing

Debug.Print mc.Value
End Sub

但程序运行出错(红色一句),Set mc = Nothing是否能触发Class_Terminate事件呢?

回复

使用道具 举报

发表于 2011-3-23 12:02 | 显示全部楼层
Terminate是类实例释放时的事件,主要是用来显示的释放一些可能不能释放的内存的.
Terminate发生后,也就是你Set mc = Nothing后,mc已经不存在了, 看不到mc的相关内容了
回复

使用道具 举报

 楼主| 发表于 2011-3-23 13:13 | 显示全部楼层
本帖最后由 Saint_Zuo 于 2011-3-23 13:55 编辑

回复 吕?布 的帖子

多谢了, 请教有什么方法可以看到释放后的value的值"def"呢?真的没有办法了吗?
还有一个问题要请教,
Option Explicit
Public Event Change(ByRef Cancel As Boolean)
Private s$

Public Property Get Value() As String '属性的读s功能
  Value = s
End Property
Public Property Let Value(ByVal c As String) '属性的写s功能
  s = c
End Property
其中属性的读功能中为什么可以不加参数,而属性的写功能为什么必须加参数ByVal c As String呢?另外这个参数的类型是否也可以变成Byref As String
呢。个人感觉这里所谓的“读”与“写”都是对s变量而言的,而不是变量value?不知道理解的是否对?

点评

你要看那个值做什么呢,如果是后面要用那个值,那也可象楼下一样,用全局变量.但是全局变量是不属于你自定义的类实例的 读属性也可以有参数的,只是要手工加工  发表于 2011-3-23 14:18
回复

使用道具 举报

发表于 2011-3-23 13:52 | 显示全部楼层
模块中
Public SC
Sub aTest()
Dim mc As New myclass

Debug.Print mc.Value

Set mc = Nothing
Debug.Print SC

End Sub

类模块:

Private Sub Class_Terminate()
SC = "def"
End Sub
回复

使用道具 举报

 楼主| 发表于 2011-3-23 14:55 | 显示全部楼层
本帖最后由 Saint_Zuo 于 2011-3-23 14:59 编辑

回复 阿童木 的帖子

运行后发现出错呀。麻烦老师再帮忙看看!

释放变量问题.rar

6.23 KB, 下载次数: 2

回复

使用道具 举报

发表于 2011-3-23 15:21 | 显示全部楼层
Option Explicit
Public Event Change(ByRef Cancel As Boolean)
Private s$
Public Property Get Value() As String '属性的读s功能
  Value = s
End Property
Public Property Let Value(ByVal c As String) '属性的写s功能
  s = c
End Property

这些代码还是要加的啊。
看来你对类模块还是不理解。
回复

使用道具 举报

 楼主| 发表于 2011-3-23 15:48 | 显示全部楼层
回复 阿童木 的帖子

的确很头疼,有好多问题不明白,还请老师多指教。请教
Public Property Let Value(ByVal c As String) '属性的写s功能
  s = Value
End Property

中为什我把 s = c改为  s = Value运行也可以呢?为什么一定要用c这个参数呢?

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-6-3 18:57 , Processed in 0.321426 second(s), 12 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表