2011-01-26 41 views
22

我試圖通過賦值語句在VB6中創建兩個相同的對象;這樣的事情...在VB6中分配對象

Dim myobj1 As Class1 
Dim myobj2 As Class1 

Set myobj1 = New Class1 
myobj1.myval = 1 
Set myobj2 = myobj1 

它已成爲明顯的是,這不會產生兩個對象,而是兩個引用同一個對象,這不是我所追求的。有什麼辦法來創造這種方式的第二個目的,還是我對象一個成員一次複製...

Set myobj2 = new Class1 
myobj2.mem1 = myobj1.mem1 
... 

編輯2 Scott Whitlock已經更新了他的優秀答案,並且將他的更改納入了這個現在可用的代碼片段。

Private Type MyMemento 
    Value1 As Integer 
    Value2 As String 
End Type 

Private Memento As MyMemento 

Public Property Let myval(ByVal newval As Integer) 
Memento.Value1 = newval 
End Property 

Public Property Get myval() As Integer 
myval = Memento.Value1 
End Property 

Friend Property Let SetMemento(new_memento As MyMemento) 
    Memento = new_memento 
End Property 

Public Function Copy() As Class1 
    Dim Result As Class1 
    Set Result = New Class1 
    Result.SetMemento = Memento 
    Set Copy = Result 
End Function 

一個隨後執行在由此代碼分配...

Set mysecondobj = myfirstobj.Copy 
+1

這個問題可能是有趣的:http://stackoverflow.com/questions/218696/cloning-objects-in-vba – 2011-01-26 14:29:07

回答

33

與許多現代語言一樣,VB6具有值類型和引用類型。類定義了引用類型。另一方面,您的基本類型如Integer是值類型。

的基本區別是在分配:

Dim a as Integer 
Dim b as Integer 
a = 2 
b = a 
a = 1 

結果是a是1和b爲2。這是因爲分配的值類型進行復印。這是因爲每個變量都有空間分配給堆棧上的(在VB6的情況下,整數在堆棧上佔用2個字節)。

對於類,它的工作方式不同:

Dim a as MyClass 
Dim b as MyClass 
Set a = New MyClass 
a.Value1 = 2 
Set b = a 
a.Value1 = 1 

的結果是,無論a.Value1b.Value1是1.這是因爲對象的狀態存儲在堆中,而不是在棧。只有參考才能將對象存儲在堆棧中,因此Set b = a將覆蓋引用。有趣的是,VB6通過強制你使用Set關鍵字來明確這一點。大多數其他現代語言不需要這個。

現在,您可以創建自己的值類型(在VB6中稱爲用戶定義類型,但在大多數其他語言中稱爲結構或結構)。這是一個tutorial

除了類是引用類型和UDT是值類型之外,類和用戶定義類型之間的區別在於類可以包含UDT無法執行的行爲(方法和屬性)。如果您只是在尋找一個記錄類的類,那麼UDT可能是您的解決方案。

您可以混合使用這些技術。假設你需要一個類,因爲你有特定的行爲和計算,你想包括數據。您可以使用memento pattern舉行UDT的內部對象的狀態:

Type MyMemento 
    Value1 As Integer 
    Value2 As String 
End Type 

在你的類,確保所有您的內部狀態的存儲MyMemento類型的私有成員內。編寫你的屬性和方法,以便它們只使用該私有成員變量中的數據。

現在製作對象的副本很簡單。只要寫所謂Copy()你的類的新方法,它返回你的類的新實例,並用自己的紀念品副本初始化:

Private Memento As MyMemento 

Friend Sub SetMemento(NewMemento As MyMemento) 
    Memento = NewMemento 
End Sub 

Public Function Copy() as MyClass 
    Dim Result as MyClass 
    Set Result = new MyClass 
    Call Result.SetMemento(Memento) 
    Set Copy = Result 
End Function 

Friend只能從東西隱藏它的項目之外,所以它不盡可能隱藏SetMemento子,但這是VB6所能做的。

HTH

+6

+1 Cleanest Memento實現我在VBx中看到過,我從來沒有考慮過使用類型作爲快捷方式。幹得好那個男人! – 2011-01-26 14:49:32

+0

@Binary Worrier - 謝謝!我知道我的l33t VB6技能有一天會派上用場......哈哈。 :) – 2011-01-26 15:20:28

2

或我必須一個成員複製的對象以時間...

不幸的是。

這是可能的(但技術上非常非常困難)用C寫一個COM服務器++是 - 使用IDispatch接口 - 將複製每個屬性的值,但實際上這是高寺編程,如果我必須這樣做,我不知道如果我可以做到這一點,但我會看看像10天的工作(我知道COM是如何在C++中實現的,我還需要調查看看ATL框架是否有任何幫助等)。

我Vb3的工作,4,5 & 6類似10年(雙手,每週5天),並沒有找到一個很好的辦法做到這一點,除了手動實現序列化模式,如紀念品和保存&商店,這實際上只是簡單地複製每個成員的複製方式,一次一個。

3

@Scott惠特洛克,我不能讓你的代碼的工作,但如果它的工作原理是將是巨大的。

我創建了一個常規的模塊,我把紀念型

Type MyMemento 
    Value1 As Integer 
    Value2 As String 
End Type 

然後,我將創建一個名爲代碼MyClass的類模塊

Private Memento As MyMemento 

Friend Sub SetMemento(NewMemento As MyMemento) 
     Memento = NewMemento 
End Sub 

Public Function Copy() as MyClass 
    Dim Result as MyClass 
    Set Result = new MyClass 
    Result.SetMemento(Memento) 
    Set Copy = Result 
End Function 

最後我嘗試調用複製功能在另一個這樣的常規模塊中

Sub Pruebas() 
    Dim Primero As MyClass, segundo As MyClass 
    Set Primero = New MyClass 
    Set segundo = New MyClass 
    Set segundo = Primero.Copy 
End Sub 

我收到消息(下圖):Error de compi lacion:薩爾瓦多TIPO德agumento德爲ByRef沒有重合

這裏是一個圖像(達到10點,因此這裏是鏈接):http://i.stack.imgur.com/KPdBR.gif

我是不是能夠用英語得到的消息,我在西班牙生活。

您是否願意在VBA Excel中提供一個示例?我一直在努力做到這一點。

謝謝你的工作

====================================== =========

編輯:問題就迎刃而解了:

問題是上線 「Result.SetMemento(記憶碎片)」,在VBA它需要與被稱爲 「呼叫」

Public Function Copy() As MyClass 
    Dim Result As MyClass 
    Set Result = New MyClass 
    Call Result.SetMemento(Memento) 
    Set Copy = Result 
End Function 

它很好用,謝謝Scott Whitlock,你是個天才