我试图通过赋值语句在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更新了他出色的答案,我已经将他的更改合并到了这个现在工作的代码片段中。
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
发布于 2011-01-26 06:43:30
与许多现代语言一样,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.Value1
和b.Value1
都是1,这是因为对象的状态存储在堆中,而不是堆栈上。只有对对象的引用存储在堆栈上,因此Set b = a
覆盖引用。有趣的是,VB6通过强制您使用Set
关键字明确地说明了这一点。大多数其他现代语言都不需要这样做。
现在,您可以创建自己的值类型(在VB6中,它们被称为用户定义类型,但在大多数其他语言中,它们被称为结构或结构)。这是一个教程。
类和用户定义类型(除了类是引用类型和UDT是值类型)之间的区别是,类可以包含UDT不能包含的行为(方法和属性)。如果您只是在寻找一个记录类型的类,那么UDT可能是您的解决方案。
您可以混合使用这些技术。假设您需要一个类,因为您有某些行为和计算,您希望将这些行为和计算与数据一起包括在内。您可以使用记忆模式在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
发布于 2011-06-26 12:07:06
@,我无法使您的代码工作,但如果它能工作,那就太棒了。
我已经创建了一个普通模块,我在其中输入了
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编译程序: El tipo de agumento de ByRef
下面是一张图片(短于10点,下面是链接):http://i.stack.imgur.com/KPdBR.gif
我没能收到英文留言,我住在西班牙。
你能在VBA Excel中提供一个例子吗?我一直在努力使这个工作。
谢谢你的工作
===============================================
编辑:问题解决:
问题是在线"Result.SetMemento(Memento)",在VBA中它需要用“调用”来调用。
Public Function Copy() As MyClass
Dim Result As MyClass
Set Result = New MyClass
Call Result.SetMemento(Memento)
Set Copy = Result
End Function
很好,谢谢斯科特惠特洛克,你是个天才
发布于 2011-01-26 06:20:53
或者我必须一次复制一个成员的对象..。
很不幸是的。
用C++编写COM服务器是可能的(但在技术上非常困难)--使用IDispatch接口--可以复制每个属性的值,但实际上这是高殿编程,如果我必须这样做,我不知道我是否可以这样做,但我需要看大约10天的工作(我知道COM是如何在C++中实现的,我还需要调查看看ATL框架是否有任何帮助等等)。
我在Vb3上工作了大约10年(一周5天,一周5天),除了手动实现像Mementos和Save&Store这样的序列化模式之外,我一直没有找到一个好的方法,这些模式实际上只是简单地归结为一次复制每个成员的奇妙方法。
https://stackoverflow.com/questions/4805475
复制相似问题