尽管如此,我仍然不理解VB6中的Object是什么(请参见http://msdn.microsoft.com/en-us/library/aa338034%28v=vs.60%29.aspx),以及Variant到底是什么。Variant是什么?在VB6中,Object是如何实现的?
VB6使用的所有对象都是COM对象。COM对象本质上是一个可变长度的数据结构,其可变长度的头包含任意数量的指向VTables的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, ..., ...)
...
唯一的其他规范是所有的VTable 必须 继承自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 中使用后期绑定(late binding)的原因。所有使用 VB6 编写的对象都自动实现了从 IDispatch 继承的接口。这被称为双重接口,因为它同时支持早期和后期绑定。
注意,COM 中没有直接的类型系统。但是,你可以选择支持 ITypeInfo 接口,以允许你的对象的用户访问你想要添加到该对象的信息(使用默认实现使用类型库来存储此信息更容易)。
正如 Bob Riemersma 所提到的那样,Variant 类型实际上是一个 16 字节的结构,其中有一个 2 字节的整数(vt),表示被封装的 Automation 类型,后面的 8 字节可以用于包含高达 8 字节的值类型或指向另一类型的 32 位指针。VB 使用其内部函数在 VB 类型和 Variant 之间进行所有必要的转换,并进行所有必要的内存分配和释放。变体可以通过将对象的指针复制到该变量中并调用该对象的 AddRef() 方法来包含对 COM 对象的引用。