2011-01-26 71 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,你是个天才