C++ VARIANT 学习小记录(转)

https://www.cnblogs.com/jiayith/p/3865058.html
C++ VARIANT 学习小记录
一:为什么会有这个?

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

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

二:VARIANT的定义

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

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

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

类型标识

三:使用例子

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

复制代码
#include
#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 = 100;
cout<<var.lVal<<endl;

var.vt = VT_R8;        //double
var.dblVal = 3.23;
cout<<var.dblVal<<endl;

cin.get();

}
复制代码
从中可以看到使用时,你要先指定这个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
复制代码
同样的目录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 = 0,
VT_NULL = 1,
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_VARIANT = 12,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_VOID = 24,
VT_HRESULT = 25,
VT_PTR = 26,
VT_SAFEARRAY = 27,
VT_CARRAY = 28,
VT_USERDEFINED = 29,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_RECORD = 36,
VT_INT_PTR = 37,
VT_UINT_PTR = 38,
VT_FILETIME = 64,
VT_BLOB = 65,
VT_STREAM = 66,
VT_STORAGE = 67,
VT_STREAMED_OBJECT = 68,
VT_STORED_OBJECT = 69,
VT_BLOB_OBJECT = 70,
VT_CF = 71,
VT_CLSID = 72,
VT_VERSIONED_STREAM = 73,
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进入源文件看看是干啥的。

下面是我看到的源码:

复制代码
1 DISPAPI KETAPITextBox::Copy( VARIANT *RHS )
2 {
3 ASSERT(m_spShape);
4 VERIFY_IN_POINTER(RHS);
5
6 HRESULT hr = m_spShape->Copy();
7 V_VT(RHS) = VT_BOOL;
8 V_BOOL(RHS) = SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE;
9
10 return hr;
11 }
复制代码
从第7行看,V_VT(RHS) = VT_BOOL; 这句话就是把RHS指向的VARIANT的vt值赋成VT的bool类型,其实也就是 RHS->vt = VARIANT的bool 这个意思了,现在这个variant表示bool啦,懂了!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值