Class VB6中对象的赋值

Class VB6中对象的赋值,class,vb6,Class,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.mem

我试图通过赋值语句在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
...
?

edit2Scott 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
或者我必须一次复制一个成员的对象

Set myobj2 = new Class1
myobj2.mem1 = myobj1.mem1
...
不幸的是,是的

<> P> >在C++中编写COM服务器是可能的(但技术上非常困难),使用IDISPoT接口将复制每个属性的值,但实际上这是高庙宇编程,如果我必须这样做,我不知道我是否能做,但我会看到像10天的工作。(我知道如何在C++中实现COM,我还需要调查,看看ATL框架是否有什么帮助)。
我在Vb3、4、5和6上工作了大约10年(亲自动手,每周5天)除了手动实现诸如Memento和Save&Store之类的序列化模式之外,从来没有找到一个好的方法来实现这一点,这实际上可以归结为一次复制每个成员的奇特方式。

与许多现代语言一样,VB6有值类型和引用类型。类定义引用类型。另一方面,您的基本类型像
Integer
这样的E是值类型

基本区别在于分配:

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通过强制使用
s来明确这一点et
关键字。大多数其他现代语言不需要这个

现在,您可以创建自己的值类型(在VB6中称为用户定义类型,但在大多数其他语言中称为结构)

类和用户定义类型(类是引用类型,UDT是值类型除外)之间的区别在于,类可以包含UDT无法包含的行为(方法和属性)。如果您只是查找记录类型类,那么UDT可能是您的解决方案

您可以混合使用这些技术。假设您需要一个类,因为您有某些行为和计算要与数据一起包含。您可以使用来保存UDT中对象的状态:

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type
在类中,确保所有内部状态都存储在类型为
MyMemento
的私有成员中。编写属性和方法,使它们仅使用该私有成员变量中的数据

现在,复制对象很简单。只需在类上编写一个名为
copy()
的新方法,该方法将返回类的新实例,并使用其自己的memento副本对其进行初始化:

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

@Scott Whitlock,我无法使您的代码正常工作,但如果它正常工作,那就太好了

我创建了一个常规模块,在其中放置memento类型

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
最后,我尝试在另一个常规模块中调用copy函数,如下所示

Sub Pruebas()
    Dim Primero As MyClass, segundo As MyClass
    Set Primero = New MyClass
    Set segundo = New MyClass
    Set segundo = Primero.Copy
End Sub
我得到了信息(下图):编译错误:El tipo de agumento de ByRef no

这是一张图片(缺少10点,所以这里是链接):

我无法用英语传达信息,我住在西班牙

请您提供一个VBA Excel中的示例,我一直在努力实现这一点

谢谢你的工作

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

编辑:问题已解决: 问题出现在“Result.SetMemento(Memento)”行上,在VBA中,需要用“Call”调用它


它工作得很好,谢谢Scott Whitlock,你是个天才

这个问题可能会引起兴趣:我喜欢如何在兴趣问题中,第二个最好的答案只是对这个问题答案的引用!:)+1我在VBx中见过的最干净的Memento实现,我从未考虑过使用类型作为快捷方式。干得好,那个人@二元烦恼-谢谢!我知道我的l33t VB6技能总有一天会派上用场。。。哈哈.)谢谢你的回答;我一直在尝试。我不得不将
类型
定义私有,并将
Me.
Me.Memento
中删除,但我无法获得
结果。Memento
要编译的部分;它响应“未找到方法或数据成员”。我能编译它的唯一方法是将所有成员公开,并一次分配一个成员。我错过什么了吗?(在问题中添加了您的代码的我的版本。)@Brian Hooper-抱歉,我的.NET再次与VB6混合。您必须在类上创建一个
SetMemento
方法。我会更新我的答案。如果你把它公开为
Friend
,我想你也得把你的类型定义为
Friend
。谢谢你,它现在玩得很开心。我觉得没有必要让
类型
成为
朋友
。实际上,你不需要
呼叫
关键字,但是你可以