2

我有一个类“投资组合”(其中类“股票”作为它的字段之一)方法,代码如下:

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

我的意思是,在每个循环中,我都会用空字段声明和初始化新的临时对象。但是在逐步运行我的程序之后,在我看来 Class_Terminate() 在循环结束时没有被调用。并且在下一步中,所有字段TempStock都已经设置为它们在前一个循环中的状态。所以,我不明白以下几点:

1) 为什么不Class_Terminate()叫 at Next i?什么时候调用?现在写对了吗?或者我是否也应该编写代码将每个非对象归档设置为空值?

2)好的,它没有被调用,但我仍然有Dim TempStock As New Stock?它不应该给我双重声明错误吗?或者TempStock至少设置为新的空对象?

3)有什么区别:

 Dim TempStock As New Stock

和:

 Dim TempStock As Stock
 Set TempStock = New Stock

它与我的问题有关吗?

对我的问题的任何部分的帮助将不胜感激,谢谢!

4

2 回答 2

4

VBA 中没有块级作用域;所有声明 ( dim) 都被提升到包含过程的顶部,并且仅在例程结束时超出范围。

您是正确的,因为您看到的行为归结为As New,目前该类将在循环内实例化一次,并且在过程返回时它退出范围之前不会终止。

要获得您想要的行为,您必须使用:

 Dim TempStock As Stock
 Set TempStock = New Stock

因为它是set显式地强制分配一个新的对象实例TempStock

当声明被提升时,该行Dim TempStock As New Stock实际上并没有立即创建 的新实例Stock,而是这种对象创建方式为跨类型变量的每次调用插入存根代码,该类型变量Stock显示“如果我不是有效的引用,现在自动创建我”。

于 2012-11-02T11:01:47.947 回答
2

如果应用语法:

Dim TempStock As Stock
Set TempStock = New Stock

析构函数被调用。
VBA 中的对象破坏发生在引用对象的引用计数为零(无)时。
在这种情况下,在每个循环中,您使用相同的变量“TempStock”来实例化一个全新的“Stock”对象,这会导致前一个对象从内存中释放。

这段代码是不必要的,因为无论如何该对象都会被销毁:

Private Sub Class_Terminate()
    Set StockDivs = Nothing
End Sub

如果您在主子程序中将 StockDivs显式设置为空,您会注意到将调用 Class_Terminate 事件,因此在这种情况下,对象在引用计数已经为零时第二次收到另一个释放消息(否则此事件不会已被调用)。

关于:

Dim TempStock As New Stock  

根据微软的说法,这两个公式是等价的:http:
//msdn.microsoft.com/en-us/library/Aa903373

但是,等价并不意味着它们是相同的。
在声明中直接使用 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

您可以在其中将多个库存添加到集合中。

于 2012-11-02T11:17:16.870 回答