据我所知,类Object在面向对象的编程语言中位于类层次结构的顶层,就像Java一样。我也明白你在.NET中有引用类型和值类型。我也理解基于C语言的类型定义。
尽管如此;我正在努力理解VB6中的Object是什么( http://msdn.microsoft.com/en-us/library/aa338034%28v=vs.60%29.aspx )以及变体到底是什么。什么是变体?如何在VB6中实现对象?
答案 0 :(得分:9)
VB6使用的所有对象都是COM对象。 COM对象本质上是一个可变长度数据结构,其可变长度头包含任意数量的指向VTable的32位指针,而成功字节包含该对象的实例数据。例如,
Bytes
0-3 VTable1 pointer
4-7 VTable2 pointer
8-11 VTable3 pointer
...
Instance data
VTable是一个由32位指针组成的数组,这些指针都传递给“this”实例指针。
Bytes
0-3 Func1(this, ..., ...)
4-7 Func2(this, ..., ...)
8-11 Func3(this, ..., ...)
...
唯一的另一个规范是所有VTables 必须继承自IUnknown,即前三个函数必须是:
QueryInterface()
AddRef()
Release()
基本上,QueryInterface()允许您查明COM对象是否支持特定接口(由UUID表示)。 AddRef()允许对象编写器增加内部引用计数。 Release()允许对象编写器递减引用计数器,在计数为零时销毁对象。你永远不会在VB中调用这些方法 - 编译器会为你添加这些调用(VB6的优势之一)。
有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/ms680509(v=vs.85).aspx。
VB'Object'类型是支持IDispatch接口的对象的引用(参见http://msdn.microsoft.com/en-us/library/windows/desktop/dd318520(v=vs.85).aspx)。这是允许你在VB和VBScript中进行后期绑定的原因。用VB6编写的所有对象都自动实现一个继承自IDispatch的接口。这称为双接口,因为它支持早期和晚期绑定。
请注意,COM中没有内置直接类型系统。但是,您可以选择支持ITypeInfo接口,该接口允许对象的用户访问您要添加的有关对象的信息(使用类型库来存储此信息的默认实现更容易)。
Bob Riemersma提到的Variant类型实际上是一个16字节结构,它有一个2字节整数(vt),表示正在封装的Automation类型,后8个字节可用于包含值类型最多8个字节,或32位指向另一个类型。 VB使用其内部函数以及所有必要的内存分配和解除分配,在VB类型和变体之间进行所有必要的转换。变量可以包含对COM对象的引用,方法是将指向对象的指针复制到Variant中,并调用对象的AddRef()方法。
答案 1 :(得分:5)
让我将其分解为不同的问题:
首先,VB6不是VB.Net,不使用.Net Framework,而是使用旧的COM框架。 (不知道你是否已经知道这一点)。
其次,您的链接指向的是VB6内置的 类 。即便如此,它称之为“物体”。他们的术语邋..
第三,也许最重要的是,在VB6中,一切都不是对象,对象甚至不是数据类型的默认或主导类别。什么是类似.Net的价值类型,但更少(大多数甚至没有运行时类型容器,只有内存中的地址)。
所以大多数数据项都不是对象,因此没有类,所以没有任何类型的继承,因此不是从其他任何东西派生的,因此没有“类型层次结构”,因此不可能有在它们的类型层次结构的“顶部”的任何东西(虽然类/对象的东西确实具有所有这些)。因此,您没有可用于任何其他数据类型的基本/根数据类型,这对于所有类型的参数传递等都是一个问题。
Variants是这个问题的一种先验解决方案,在早期版本的VB中实现(早于VB中的Objects)来解决这个问题。 Variant只是一个动态描述符,它包含了任何数据类型的另一项。当你使用它时(通常)就像你直接使用它包含的东西一样,但是你真的要通过通过 Variant来获取它当前碰巧包含的任何类型的数据项。
Variant本身会跟踪其内容的数据类型,并使访问它的VB代码的行为方式不同/适当(一种原始的多态)。
如果这听起来像它的kludgy并且是很多开销,那么,它就是。但是当你需要处理“任何数据类型”时,它是当时最好的解决方案。