Class 在for()循环中声明和初始化的VBA对象的范围
我有一个类“Portfolio”(它的字段之一是类“Stock”)方法,代码如下:Class 在for()循环中声明和初始化的VBA对象的范围,class,vba,scope,Class,Vba,Scope,我有一个类“Portfolio”(它的字段之一是类“Stock”)方法,代码如下: For i = 1 To n Dim TempStock As New Stock TempStock.Set_Stock 'sets TempStock ... Next i 其中“Stock”是我的用户定义类,具有以下结构、构造函数和析构函数: Private StockName As String Private CurDate As Date Pri
For i = 1 To n
Dim TempStock As New Stock
TempStock.Set_Stock 'sets TempStock
...
Next i
其中“Stock”是我的用户定义类,具有以下结构、构造函数和析构函数:
Private StockName As String
Private CurDate As Date
Private BidPrice As Double
Private AskPrice As Double
Private StockDivs As Dictionary
Private Sub Class_Initialize()
Set StockDivs = New Dictionary
End Sub
Private Sub Class_Terminate()
Set StockDivs = Nothing
End Sub
我的意思是,在每个循环中,我将声明并初始化带有空字段的新临时对象。但是在一步一步地运行我的程序之后,在我看来类_Terminate()并没有在循环结束时被调用。在下一步中,TempStock
的所有字段都已设置为上一个循环中的字段。因此,我不理解以下内容:
1) 为什么不在下一个i调用Class_Terminate()
?什么时候叫?现在写对了吗?或者我也应该编写代码,将每个非对象字段设置为空值
2) 好的,它没有被调用,但我仍然有Dim TempStock作为新股票
?它不应该给我双重声明错误吗?或者至少将TempStock
设置为新的空对象
3) 以下两者之间的区别是什么:
Dim TempStock As New Stock
以及:
这和我的问题有关吗
如果您能帮我解决任何问题,我们将不胜感激,谢谢 VBA中没有块级范围;所有声明(
dim
)都被提升到包含过程的顶部,并且仅在例程结束时超出范围
您是正确的,因为您看到的行为是新的,当前该类将在循环中实例化一次&直到过程返回时它退出范围后才终止
要获得您想要的行为,您必须使用:
Dim TempStock As Stock
Set TempStock = New Stock
因为是集合
显式地强制将新对象实例分配给TempStock
当声明被挂起时,Dim TempStock As New Stock
行实际上不会立即创建Stock
的新实例,相反,这种对象创建方式会为跨越Stock
类型变量的每次调用插入存根代码,该变量表示“如果我不是有效引用,请立即自动创建我”.如果应用语法:
Dim TempStock As Stock
Set TempStock = New Stock
将调用析构函数。
VBA中的对象销毁发生在引用对象的引用计数为零(无)时。
在本例中,在每个循环中,您都使用相同的变量“TempStock”实例化一个全新的“Stock”对象,该对象将导致前一个对象从内存中释放
这段代码是不必要的,因为对象将被销毁:
Private Sub Class_Terminate()
Set StockDivs = Nothing
End Sub
如果在main sub中将StockDivs显式设置为nothing,则会注意到类_Terminate事件将被调用,因此在这种情况下,对象将在引用计数为零时第二次接收另一个释放消息(否则将不会调用此事件)
关于:
Dim TempStock As New Stock
根据微软的说法,这两个公式是等价的:
然而,等效并不意味着它们完全相同。
在声明中直接使用New关键字确实也会实例化Stock对象,但是正如您所注意到的,构造函数只被调用一次,析构函数只在循环结束时被调用。这意味着您在每个循环中反复使用同一对象,同时在同一对象上重新分配属性(但实际上没有释放它)。
这个公式的典型特点是,对象上的初始值设定项不是在声明时调用的,而是在首次使用后才调用。
在大多数用例中,两者最终都可以使用相同的结果
我猜你可能有用的是下面的代码。
除非您想将多个股票添加到集合中(您也可以使用字典),否则我看不出在分配属性时多次循环同一类的直接原因
Option Explicit
Sub Stocks()
Dim oCollection As Collection
Dim TempStock As Stock
Dim lCnt As Long
Set oCollection = New Collection
For lCnt = 1 To 5
Set TempStock = New Stock
TempStock.Set_Stock ("Stock_" & lCnt) 'sets TempStock name eg.
oCollection.Add TempStock
Next lCnt
End Sub
将多个股票添加到集合中 但此时第二个循环中的“旧”TempStock对象会发生什么:Set TempStock=newstock?是否调用了Class_Terminate()?第二次调用Set TempStock=New Stock
会导致Class_在新实例上初始化,然后在现有实例上终止。Class_Terminate是一个在引用计数达到零时自动调用的事件。由于变量Tempstock在每个循环的堆上都被分配了一个“新”对象,因此前一个对象被释放,并且该(已释放)对象上的析构函数被调用。TempStock被声明为持有一个类对象,因此不能持有多个实例,比如一个集合。啊,我明白了!代码中还有另一个对象引用了TempStock,因此在“New”之后不会立即调用析构函数,而是在该引用终止时调用析构函数。
Option Explicit
Sub Stocks()
Dim oCollection As Collection
Dim TempStock As Stock
Dim lCnt As Long
Set oCollection = New Collection
For lCnt = 1 To 5
Set TempStock = New Stock
TempStock.Set_Stock ("Stock_" & lCnt) 'sets TempStock name eg.
oCollection.Add TempStock
Next lCnt
End Sub