在VB6中分配对象

时间:2011-01-26 14:12:55

标签: 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.mem1
...

编辑2 斯科特·惠特洛克已经更新了他的优秀答案,并将他的更改纳入了这个现在正在运行的代码段。

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

3 个答案:

答案 0 :(得分:38)

与许多现代语言一样,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 sub并没有太大作用,但是你可以用VB6做些什么。

HTH

答案 1 :(得分:3)

@Scott Whitlock,我无法使你的代码工作,但如果它有效,那就太棒了。

我已经创建了一个常规模块,我将其放入纪念品类型

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

我收到消息(图片下方):错误编辑:El tipo de agumento de ByRef no coincide

这是一张图片(缺少10分,所以这里是链接):http://i.stack.imgur.com/KPdBR.gif

我无法用英语接收消息,我住在西班牙。

你是否愿意在VBA Excel中提供一个例子?我一直在努力做到这一点。

感谢您的工作

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

编辑:解决问题:

问题出在线上“Result.SetMemento(Memento)”,在VBA中需要通过“Call”调用

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

它很棒,感谢Scott Whitlock,你是个天才

答案 2 :(得分:2)

  

或者我是否必须一次复制一个成员...

不幸的是,是的。

有可能(但在技术上非常非常很难)用C ++编写COM服务器 - 使用IDispatch接口 - 将复制每个属性的值,但实际上这是高寺庙编程,如果我必须这样做,我不知道我是否可以这样做,但我会看到像10天工作的东西(我知道如何COM是用C ++实现的,我还需要调查看看ATL框架是否有任何帮助等等。

我曾与Vb3,4,5&虽然手动实现Mementos和Save& amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp;商店,这真的只是简单地模仿复制每个成员的方式,一次一个。