一:为什么会有这个?

  目前,计算机语言有很多(大哥,为什么不能就那么一样呢?),如C++、Java,此外还有JavaScript、VBScript等脚本语言,它们自立门派,各自维护自己的数据类型。

  C++是一种强类型语言,即C++中的某个变量,在使用时类型已经确定,C++中的变量都会被翻译成准确的内存地址和大小,如果类型不确定是不可能处理的。当使用C++这样强类型的语言来读取数据库或者与其他语言之间来交换数据时,它很有可能不知道获取到的数据的具体类型,这个时候必须借助于变体类型读取数据。VARIANT数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。




二:VARIANT的定义

  在我的windows C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include下OAIdl.h有这个东东的定义:

typedef /* [wire_marshal] */ struct tagVARIANT VARIANT;

struct tagVARIANT
{
union
{
struct __tagVARIANT
{
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union
{
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
_VARIANT_BOOL bool;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown *punkVal;
IDispatch *pdispVal;
SAFEARRAY *parray;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
LONGLONG *pllVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
_VARIANT_BOOL *pbool;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
IUnknown **ppunkVal;
IDispatch **ppdispVal;
SAFEARRAY **pparray;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
ULONGLONG ullVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
ULONGLONG *pullVal;
INT *pintVal;
UINT *puintVal;
struct __tagBRECORD
{
PVOID pvRecord;
IRecordInfo *pRecInfo;
} __VARIANT_NAME_4;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
} ;
typedef VARIANT *LPVARIANT; typedef VARIANT VARIANTARG; typedef VARIANT *LPVARIANTARG;

variant

看,就是这个东西。太难看了,下面是一个文件简化的让人看的:

struct tagVARIANT
{
union
{
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union
{
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
DATE date;
BSTR bstrVal;
SAFEARRAY *parray;
VARIANT *pvarVal;
};
};
};

简化

  VARIANT数据结构包含两个域(如果不考虑保留的域)。vt域描述了第二个域的数据类型。为了使多种类型能够在第二个域中出现,定义了一个联合结构。所以,第二个域的名称随着vt域中输入值的不同而改变。下面是同一个文件的里面的东东,这个东西是vt域可以赋哪些值及这些值代表什么变量类型:

/* VARIANT STRUCTURE
*
* VARTYPE vt;
* WORD wReserved1;
* WORD wReserved2;
* WORD wReserved3;
* union {
* LONGLONG VT_I8
* LONG VT_I4
* BYTE VT_UI1
* SHORT VT_I2
* FLOAT VT_R4
* DOUBLE VT_R8
* VARIANT_BOOL VT_BOOL
* SCODE VT_ERROR
* CY VT_CY
* DATE VT_DATE
* BSTR VT_BSTR
* IUnknown * VT_UNKNOWN
* IDispatch * VT_DISPATCH
* SAFEARRAY * VT_ARRAY
* BYTE * VT_BYREF|VT_UI1
* SHORT * VT_BYREF|VT_I2
* LONG * VT_BYREF|VT_I4
* LONGLONG * VT_BYREF|VT_I8
* FLOAT * VT_BYREF|VT_R4
* DOUBLE * VT_BYREF|VT_R8
* VARIANT_BOOL * VT_BYREF|VT_BOOL
* SCODE * VT_BYREF|VT_ERROR
* CY * VT_BYREF|VT_CY
* DATE * VT_BYREF|VT_DATE
* BSTR * VT_BYREF|VT_BSTR
* IUnknown ** VT_BYREF|VT_UNKNOWN
* IDispatch ** VT_BYREF|VT_DISPATCH
* SAFEARRAY ** VT_BYREF|VT_ARRAY
* VARIANT * VT_BYREF|VT_VARIANT
* PVOID VT_BYREF (Generic ByRef)
* CHAR VT_I1
* USHORT VT_UI2
* ULONG VT_UI4
* ULONGLONG VT_UI8
* INT VT_INT
* UINT VT_UINT
* DECIMAL * VT_BYREF|VT_DECIMAL
* CHAR * VT_BYREF|VT_I1
* USHORT * VT_BYREF|VT_UI2
* ULONG * VT_BYREF|VT_UI4
* ULONGLONG * VT_BYREF|VT_UI8
* INT * VT_BYREF|VT_INT
* UINT * VT_BYREF|VT_UINT
* }
*/

类型标识




三:使用例子

  看一个小例子就知道怎么用了:

#include <iostream>
#include <OAIdl.h> using namespace std; int main(void)
{
VARIANT var;
cout<<sizeof(VARIANT)<<endl; var.vt = VT_BOOL; //bool
var.boolVal = true;
cout<<var.boolVal<<endl; var.vt = VT_I4; //long
var.lVal = ;
cout<<var.lVal<<endl; var.vt = VT_R8; //double
var.dblVal = 3.23;
cout<<var.dblVal<<endl; cin.get();
}

C++例子

从中可以看到使用时,你要先指定这个variant是个什么玩意儿,然后给那个玩意儿赋值,输出的时候也要输出那个玩意儿的值,乖点总没错。输出:




四:还有一点

  在使用VARIANT的时候,经常会用到一些它给定的宏,这些宏可以很方便地对VARIANT指定类型及赋值,在我的 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include 下的oleauto.h里面就有:

// Declare variant access functions.

#if __STDC__ || defined(NONAMELESSUNION)
#define V_UNION(X, Y) ((X)->n1.n2.n3.Y)
#define V_VT(X) ((X)->n1.n2.vt)
#define V_RECORDINFO(X) ((X)->n1.n2.n3.brecVal.pRecInfo)
#define V_RECORD(X) ((X)->n1.n2.n3.brecVal.pvRecord)
#else
#define V_UNION(X, Y) ((X)->Y)
#define V_VT(X) ((X)->vt)
#define V_RECORDINFO(X) ((X)->pRecInfo)
#define V_RECORD(X) ((X)->pvRecord)
#endif /* Variant access macros
*/
#define V_ISBYREF(X) (V_VT(X)&VT_BYREF)
#define V_ISARRAY(X) (V_VT(X)&VT_ARRAY)
#define V_ISVECTOR(X) (V_VT(X)&VT_VECTOR)
#define V_NONE(X) V_I2(X) #define V_UI1(X) V_UNION(X, bVal)
#define V_UI1REF(X) V_UNION(X, pbVal)
#define V_I2(X) V_UNION(X, iVal)
#define V_I2REF(X) V_UNION(X, piVal)
#define V_I4(X) V_UNION(X, lVal)
#define V_I4REF(X) V_UNION(X, plVal)
#define V_I8(X) V_UNION(X, llVal)
#define V_I8REF(X) V_UNION(X, pllVal)
#define V_R4(X) V_UNION(X, fltVal)
#define V_R4REF(X) V_UNION(X, pfltVal)
#define V_R8(X) V_UNION(X, dblVal)
#define V_R8REF(X) V_UNION(X, pdblVal)
#define V_I1(X) V_UNION(X, cVal)
#define V_I1REF(X) V_UNION(X, pcVal)
#define V_UI2(X) V_UNION(X, uiVal)
#define V_UI2REF(X) V_UNION(X, puiVal)
#define V_UI4(X) V_UNION(X, ulVal)
#define V_UI4REF(X) V_UNION(X, pulVal)
#define V_UI8(X) V_UNION(X, ullVal)
#define V_UI8REF(X) V_UNION(X, pullVal)
#define V_INT(X) V_UNION(X, intVal)
#define V_INTREF(X) V_UNION(X, pintVal)
#define V_UINT(X) V_UNION(X, uintVal)
#define V_UINTREF(X) V_UNION(X, puintVal) #ifdef _WIN64
#define V_INT_PTR(X) V_UNION(X, llVal)
#define V_UINT_PTR(X) V_UNION(X, ullVal)
#define V_INT_PTRREF(X) V_UNION(X, pllVal)
#define V_UINT_PTRREF(X) V_UNION(X, pullVal)
#else
#define V_INT_PTR(X) V_UNION(X, lVal)
#define V_UINT_PTR(X) V_UNION(X, ulVal)
#define V_INT_PTRREF(X) V_UNION(X, plVal)
#define V_UINT_PTRREF(X) V_UNION(X, pulVal)
#endif #define V_CY(X) V_UNION(X, cyVal)
#define V_CYREF(X) V_UNION(X, pcyVal)
#define V_DATE(X) V_UNION(X, date)
#define V_DATEREF(X) V_UNION(X, pdate)
#define V_BSTR(X) V_UNION(X, bstrVal)
#define V_BSTRREF(X) V_UNION(X, pbstrVal)
#define V_DISPATCH(X) V_UNION(X, pdispVal)
#define V_DISPATCHREF(X) V_UNION(X, ppdispVal)
#define V_ERROR(X) V_UNION(X, scode)
#define V_ERRORREF(X) V_UNION(X, pscode)
#define V_BOOL(X) V_UNION(X, boolVal)
#define V_BOOLREF(X) V_UNION(X, pboolVal)
#define V_UNKNOWN(X) V_UNION(X, punkVal)
#define V_UNKNOWNREF(X) V_UNION(X, ppunkVal)
#define V_VARIANTREF(X) V_UNION(X, pvarVal)
#define V_ARRAY(X) V_UNION(X, parray)
#define V_ARRAYREF(X) V_UNION(X, pparray)
#define V_BYREF(X) V_UNION(X, byref) #define V_DECIMAL(X) V_UNION(X, decVal)
#define V_DECIMALREF(X) V_UNION(X, pdecVal) #ifndef RC_INVOKED
#include <poppack.h>
#endif // RC_INVOKED #endif // __OLEAUTO_H__

Variant宏

同样的目录wtypes.h下也有:

typedef unsigned short VARTYPE;

/*
* VARENUM usage key,
*
* * [V] - may appear in a VARIANT
* * [T] - may appear in a TYPEDESC
* * [P] - may appear in an OLE property set
* * [S] - may appear in a Safe Array
*
*
* VT_EMPTY [V] [P] nothing
* VT_NULL [V] [P] SQL style Null
* VT_I2 [V][T][P][S] 2 byte signed int
* VT_I4 [V][T][P][S] 4 byte signed int
* VT_R4 [V][T][P][S] 4 byte real
* VT_R8 [V][T][P][S] 8 byte real
* VT_CY [V][T][P][S] currency
* VT_DATE [V][T][P][S] date
* VT_BSTR [V][T][P][S] OLE Automation string
* VT_DISPATCH [V][T] [S] IDispatch *
* VT_ERROR [V][T][P][S] SCODE
* VT_BOOL [V][T][P][S] True=-1, False=0
* VT_VARIANT [V][T][P][S] VARIANT *
* VT_UNKNOWN [V][T] [S] IUnknown *
* VT_DECIMAL [V][T] [S] 16 byte fixed point
* VT_RECORD [V] [P][S] user defined type
* VT_I1 [V][T][P][s] signed char
* VT_UI1 [V][T][P][S] unsigned char
* VT_UI2 [V][T][P][S] unsigned short
* VT_UI4 [V][T][P][S] unsigned long
* VT_I8 [T][P] signed 64-bit int
* VT_UI8 [T][P] unsigned 64-bit int
* VT_INT [V][T][P][S] signed machine int
* VT_UINT [V][T] [S] unsigned machine int
* VT_INT_PTR [T] signed machine register size width
* VT_UINT_PTR [T] unsigned machine register size width
* VT_VOID [T] C style void
* VT_HRESULT [T] Standard return type
* VT_PTR [T] pointer type
* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)
* VT_CARRAY [T] C style array
* VT_USERDEFINED [T] user defined type
* VT_LPSTR [T][P] null terminated string
* VT_LPWSTR [T][P] wide null terminated string
* VT_FILETIME [P] FILETIME
* VT_BLOB [P] Length prefixed bytes
* VT_STREAM [P] Name of the stream follows
* VT_STORAGE [P] Name of the storage follows
* VT_STREAMED_OBJECT [P] Stream contains an object
* VT_STORED_OBJECT [P] Storage contains an object
* VT_VERSIONED_STREAM [P] Stream with a GUID version
* VT_BLOB_OBJECT [P] Blob contains an object
* VT_CF [P] Clipboard format
* VT_CLSID [P] A Class ID
* VT_VECTOR [P] simple counted array
* VT_ARRAY [V] SAFEARRAY*
* VT_BYREF [V] void* for local use
* VT_BSTR_BLOB Reserved for system use
*/ enum VARENUM
{ VT_EMPTY = ,
VT_NULL = ,
VT_I2 = ,
VT_I4 = ,
VT_R4 = ,
VT_R8 = ,
VT_CY = ,
VT_DATE = ,
VT_BSTR = ,
VT_DISPATCH = ,
VT_ERROR = ,
VT_BOOL = ,
VT_VARIANT = ,
VT_UNKNOWN = ,
VT_DECIMAL = ,
VT_I1 = ,
VT_UI1 = ,
VT_UI2 = ,
VT_UI4 = ,
VT_I8 = ,
VT_UI8 = ,
VT_INT = ,
VT_UINT = ,
VT_VOID = ,
VT_HRESULT = ,
VT_PTR = ,
VT_SAFEARRAY = ,
VT_CARRAY = ,
VT_USERDEFINED = ,
VT_LPSTR = ,
VT_LPWSTR = ,
VT_RECORD = ,
VT_INT_PTR = ,
VT_UINT_PTR = ,
VT_FILETIME = ,
VT_BLOB = ,
VT_STREAM = ,
VT_STORAGE = ,
VT_STREAMED_OBJECT = ,
VT_STORED_OBJECT = ,
VT_BLOB_OBJECT = ,
VT_CF = ,
VT_CLSID = ,
VT_VERSIONED_STREAM = ,
VT_BSTR_BLOB = 0xfff,
VT_VECTOR = 0x1000,
VT_ARRAY = 0x2000,
VT_BYREF = 0x4000,
VT_RESERVED = 0x8000,
VT_ILLEGAL = 0xffff,
VT_ILLEGALMASKED = 0xfff,
VT_TYPEMASK = 0xfff
} ;

枚举等

在调试的时候看到了这种难看的就按 Alt+G进入源文件看看是干啥的。

  下面是我看到的源码:

 DISPAPI KETAPITextBox::Copy( VARIANT *RHS )
{
ASSERT(m_spShape);
VERIFY_IN_POINTER(RHS); HRESULT hr = m_spShape->Copy();
V_VT(RHS) = VT_BOOL;
V_BOOL(RHS) = SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE; return hr;
}

从第7行看,V_VT(RHS) = VT_BOOL; 这句话就是把RHS指向的VARIANT的vt值赋成VT的bool类型,其实也就是 RHS->vt = VARIANT的bool 这个意思了,现在这个variant表示bool啦,懂了!

C++ VARIANT 学习小记录的更多相关文章

  1. COM 学习小记录

    COM组件程序:模块,它可以是 动态连接库(DLL) && 可执行程序(EXE),称为 进程内组件(in-of-process component) && 进程外组件( ...

  2. Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)

    Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...

  3. Java 需要记得、了解的关键词 (Java 学习中的小记录)

    Java 需要记得.了解的关键词 (Java 学习中的小记录)     作者:王可利(Star·星星) 总结:本次随笔,仅且拿来平时翻阅记忆用

  4. 关于HTML中,绝对定位,相对定位的理解...(学习HTML过程中的小记录)

    关于HTML中,绝对定位,相对定位的理解...(学习HTML过程中的小记录)   作者:王可利(Star·星星) HTML中 相对定位:position:relative; 绝对定位:position ...

  5. 利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)

    利用JQ实现的,高仿 彩虹岛官网导航栏(学习HTML过程中的小记录)   作者:王可利(Star·星星) 总结: 今天学习的jQ类库的使用,代码重复的比较多需要完善.严格区分大小写,在 $(" ...

  6. html/css 盒子布局 Margin 、Padding 、border 以及 清除浮动的知识 (学习HTML过程中的小记录)

    html/css  盒子布局 Margin .Padding .border 以及 清除浮动的知识 (学习HTML过程中的小记录) 作者:王可利(Star·星星) width     是"宽 ...

  7. Android学习小Demo(19)利用Loader来实时接收短信

    之前写过一篇文章<Android学习小Demo(13)Android中关于ContentObserver的使用>,在里面利用ContentOberver去监測短信URI内容的变化.我们先来 ...

  8. 跟我一起,利用bitcms内容管理系统从0到1学习小程序开发:一、IIS下SSL环境搭建

    缘起 1.从事互联网十来年了,一直想把自己的从事开发过程遇到的问题给写出来,分享给大家.可是可是这只是个种想法,想想之后就放下了,写出来的类文章是少之又少.古人说无志之人常立志,有志之人立长志.今天, ...

  9. Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

随机推荐

  1. Cucumber 入门一

    (转自:http://www.cnblogs.com/jarodzz/archive/2012/07/02/2573014.html) 第一次看到Cucumber和BDD(Behavior Drive ...

  2. 【VBA研究】怎样将单元格数据赋给数组

    作者:iamlaosong 将工作表中的数据赋给数组或者将数组的数据赋给工作表,一般有两种.一种是循环的方法,一个一个的传,这样的方法一般用于须要对每一个数据特别处理的场合,还有一种是一次性用赋值语句 ...

  3. replace和insert的语句插入(转)

    SELECT INTO 和 INSERT INTO SELECT 两种表复制语句 Insert是T-sql中常用语句,Insert INTO table(field1,field2,...) valu ...

  4. Asp.Net+Extjs实现登录

    通过对Ext的学习,发现学习分三部曲:1.看官网的Demo,宏观了解Ext能做什么:2.看相关书籍,做理论指导:3.实现官网的Demo,体会Ext的真谛. 在完毕了第一.二部后,如今我们须要做的是实现 ...

  5. JS 文本输入框放大镜效果

    JS 文本输入框放大镜效果 今天下午研究了下 "文本输入框放大镜效果" 当然KISSY官网也有这种组件 请看kissy demo 其实这种效果 对于很多童鞋来说 应该并不陌生!我今 ...

  6. dubbo-RPC学习(二) http protocol

    dubbo中的协议默认支持很多种,从简单的开始,先解读HttpProtocol吧. dubbo中的http-RPC基于spring web支持的http invoker,web容器默认使用jetty. ...

  7. Jordan Lecture Note-9: Principal Components Analysis (PCA).

    Principal Components Analysis (一)引入PCA    当我们对某个系统或指标进行研究时往往会发现,影响这些系统和指标的因素或变量的数量非常的多.多变量无疑会为科学研究带来 ...

  8. 炼数成金hadoop视频干货06-10

    视频地址:http://pan.baidu.com/s/1dDEgKwD 第六课统讲了hadoop几个子项目和HBase,第七课还是讲的HBase 第八课讲了PIG 第九课讲了Hive和Zookeep ...

  9. Android(java)学习笔记114:LayoutInflater和findViewById

    1. 在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById(). 不同点是LayoutInflater是用来找res/layout/下的xml布局文件, ...

  10. iOS之与JS交互通信

    随着苹果SDK的不断升级,越来越多的新特性增加了进来,本文主要讲述从iOS6至今,Native与JavaScript的交互方法 一.UIWebview && iframe && ...