HYPERLINK"http://blog.csdn.net/zhangqc1985/article/details/4704038"C++变体数据类型——VARIANT--zz:http://blog.csdn.net/zhangqc1985/article/details/47040382009-10-2015:41 3601人阅读 HYPERLINK"http://blog.csdn.net/zhangqc1985/article/details/4704038"\l"comments"评论(0) HYPERLINK"javascript:void(0);"\o"收藏"\t"_blank"收藏 HYPERLINK"http://blog.csdn.net/zhangqc1985/article/details/4704038"\l"report"\o"举报"举报版权声明:本文为博主原创文章,未经博主允许不得转载。百度百科:Variant音标Phoneticsymbol [] 词性及解释Partofspeechanddefination n.变体,异体 a.不同的,有差别的 【计】变体型 【化】变体 【医】变异的;变异体,变型,变种 Variant数据类型是所有没被显式声明(用如Dim、Private、Public或Static等语句)为其他类型变量的数据类型。Variant数据类型并没有类型声明字符。 Variant是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant也可以包含Empty、Error、Nothing及Null等特殊值。可以用VarType函数或TypeName函数来决定如何处理Variant中的数据。 数值数据可以是任何整型或实型数,负数时范围从-1.797693134862315E308到-4.94066E-324,正数时则从4.94066E-324到1.797693134862315E308。通常,数值Variant数据保持为其Variant中原来的数据类型。例如,如果把一个Integer赋值给Variant,则接下来的运算会把此Variant当成Integer来处理。然而,如果算术运算针对含Byte、Integer、Long或Single之一的Variant执行,并当结果超过原来数据类型的正常范围时,则在Variant中的结果会提升到较大的数据类型。如Byte则提升到Integer,Integer则提升到Long,而Long和Single则提升为Double。当Variant变量中有Currency、Decimal及Double值超过它们各自的范围时,会发生错误。 可以用Variant数据类型来替换任何数据类型,这样会更有适应性。如果Variant变量的内容是数字,它可以用字符串来表示数字或是用它实际的值来表示,这将由上下文来决定,例如: DimMyVarAsVariant MyVar=98052 在前面的例子中,MyVar内有一实际值为98052的数值。像期望的那样,算术运算子可以对Variant变量运算,其中包含数值或能被解释为数值的字符串数据。如果用+运算子来将MyVar与其他含有数字的Variant或数值类型的变量相加,结果便是一算术和。 Empty值用来标记尚未初始化(给定初始值)的Variant变量。内含Empty的Variant在数值的上下文中表示0,如果是用在字符串的上下文中则表示零长度的字符串("")。 不应将Empty与Null弄混。Null是表示Variant变量确实含有一个无效数据。 在Variant中,Error是用来指示在过程中出现错误时的特殊值。然而,不像对其他种类的错误那样,程序并不产生普通的应用程序级的错误处理。这可以让程序员,或应用程序本身,根据此错误值采取另外的行动。可以用CVErr函数将实数转换为错误值来产生Error值。 变体类型Variant 变体类型Variant,能够在运行期间动态的改变类型。变体类型能支持所有简单的数据类型,如整型、浮点、字符串、布尔型、日期时间、货币及OLE自动化对象等,不能够表达ObjectPascal对象。 VARIANT数据类型在文件OAIDL.IDL中定义如下:struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { ULONGLONG ullVal; /* VT_UI8 */ LONGLONG llVal; /* VT_I8 */ LONG lVal; /* VT_I4 */ BYTE bVal; /* VT_UI1 */ SHORT iVal; /* VT_I2 */ FLOAT fltVal; /* VT_R4 */ DOUBLE dblVal; /* VT_R8 */ VARIANT_BOOL boolVal; /* VT_BOOL */ _VARIANT_BOOL bool; /* (obsolete) */ SCODE scode; /* VT_ERROR */ CY cyVal; /* VT_CY */ DATE date; /* VT_DATE */ BSTR bstrVal; /* VT_BSTR */ IUnknown * punkVal; /* VT_UNKNOWN */ IDispatch * pdispVal; /* VT_DISPATCH */ SAFEARRAY * parray; /* VT_ARRAY */ BYTE * pbVal; /* VT_BYREF|VT_UI1 */ SHORT * piVal; /* VT_BYREF|VT_I2 */ LONG * plVal; /* VT_BYREF|VT_I4 */ LONGLONG * pllVal; /* VT_BYREF|VT_I8 */ FLOAT * pfltVal; /* VT_BYREF|VT_R4 */ DOUBLE * pdblVal; /* VT_BYREF|VT_R8 */ VARIANT_BOOL *pboolVal; /* VT_BYREF|VT_BOOL */ _VARIANT_BOOL *pbool; /* (obsolete) */ SCODE * pscode; /* VT_BYREF|VT_ERROR */ CY * pcyVal; /* VT_BYREF|VT_CY */ DATE * pdate; /* VT_BYREF|VT_DATE */ BSTR * pbstrVal; /* VT_BYREF|VT_BSTR */ IUnknown ** ppunkVal; /* VT_BYREF|VT_UNKNOWN */ IDispatch ** ppdispVal; /* VT_BYREF|VT_DISPATCH */ SAFEARRAY ** pparray; /* VT_BYREF|VT_ARRAY */ VARIANT * pvarVal; /* VT_BYREF|VT_VARIANT */ PVOID byref; /* Generic ByRef */ CHAR cVal; /* VT_I1 */ USHORT uiVal; /* VT_UI2 */ ULONG ulVal; /* VT_UI4 */ INT intVal; /* VT_INT */ UINT uintVal; /* VT_UINT */ DECIMAL * pdecVal; /* VT_BYREF|VT_DECIMAL */ CHAR * pcVal; /* VT_BYREF|VT_I1 */ USHORT * puiVal; /* VT_BYREF|VT_UI2 */ ULONG * pulVal; /* VT_BYREF|VT_UI4 */ ULONGLONG * pullVal; /* VT_BYREF|VT_UI8 */ INT * pintVal; /* VT_BYREF|VT_INT */ UINT * puintVal; /* VT_BYREF|VT_UINT */ struct __tagBRECORD { PVOID pvRecord; IRecordInfo * pRecInfo; } __VARIANT_NAME_4; /* VT_RECORD */ } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; }; VARIANT数据结构包含两个域(如果不考虑保留的域)。vt域描述了第二个域的数据类型。为了使多种类型能够在第二个域中出现,我们定义了一个联合结构。所以,第二个域的名称随着vt域中输入值的不同而改变。用于指定vt域值情况的常量在联合的定义中以每一行的注释形式给出。使用VARIANT和VARIANTARG数据结构要分两步完全。举一个例子,让我们考虑如下代码:longlValue=999;VARIANTvParam;vParam.vt=VT_I4;vParam.lVal=lValue;在第一行中指定数据类型。常量VT_I4表明在第二个域中将出现一个long型的数据。根据类型VARIANT的定义,可以得知,当一个long型数据存入VARIANT类型时,其第二个域使用的名称是lVal。使用VARIANT来传递参数意味着非强类型语言(例如VBScript)能够调用使用强类型语言(C++)实现的方法。Invoke()方法的实现可以检查参数VARIANT封装的数值是否符合其正确的数据类型。如果符合,该类型将取出,并传递给调用方法。否则,Invoke()方法能够尝试使用VariantChangeType()API函数来将该数值转换成正确的类型。typedefunsignedshortVARTYPE;/* *VARENUMusagekey, * **[V]-mayappearinaVARIANT **[T]-mayappearinaTYPEDESC **[P]-mayappearinanOLEpropertyset **[S]-mayappearinaSafeArray * * * VT_EMPTY [V] [P] nothing * VT_NULL [V] [P] SQLstyleNull * VT_I2 [V][T][P][S] 2bytesignedint * VT_I4 [V][T][P][S] 4bytesignedint * VT_R4 [V][T][P][S] 4bytereal * VT_R8 [V][T][P][S] 8bytereal * VT_CY [V][T][P][S] currency * VT_DATE [V][T][P][S] date * VT_BSTR [V][T][P][S] OLEAutomationstring * 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] 16bytefixedpoint * VT_RECORD [V] [P][S] userdefinedtype * VT_I1 [V][T][P][s] signedchar * VT_UI1 [V][T][P][S] unsignedchar * VT_UI2 [V][T][P][S] unsignedshort * VT_UI4 [V][T][P][S] unsignedlong * VT_I8 [T][P] signed64-bitint * VT_UI8 [T][P] unsigned64-bitint * VT_INT [V][T][P][S] signedmachineint * VT_UINT [V][T] [S] unsignedmachineint * VT_INT_PTR [T] signedmachineregistersizewidth * VT_UINT_PTR [T] unsignedmachineregistersizewidth * VT_VOID [T] Cstylevoid * VT_HRESULT [T] Standardreturntype * VT_PTR [T] pointertype * VT_SAFEARRAY [T] (useVT_ARRAYinVARIANT) * VT_CARRAY [T] Cstylearray * VT_USERDEFINED [T] userdefinedtype * VT_LPSTR [T][P] nullterminatedstring * VT_LPWSTR [T][P] widenullterminatedstring * VT_FILETIME [P] FILETIME * VT_BLOB [P] Lengthprefixedbytes * VT_STREAM [P] Nameofthestreamfollows * VT_STORAGE [P] Nameofthestoragefollows * VT_STREAMED_OBJECT [P] Streamcontainsanobject * VT_STORED_OBJECT [P] Storagecontainsanobject * VT_VERSIONED_STREAM [P] StreamwithaGUIDversion * VT_BLOB_OBJECT [P] Blobcontainsanobject * VT_CF [P] Clipboardformat * VT_CLSID [P] AClassID * VT_VECTOR [P] simplecountedarray * VT_ARRAY [V] SAFEARRAY* * VT_BYREF [V] void*forlocaluse * VT_BSTR_BLOB Reservedforsystemuse */enumVARENUM { 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 }; 例子://(1).定义变量,如:intuIsRead=10;DOUBLEbVal[]={0,1,2,3,4,5,6,7,8,9};//(2).创建SafeArray描述符:SAFEARRAY*psa;SAFEARRAYBOUNDrgsabound[1];//={10,1};rgsabound[0].cElements=uIsRead;rgsabound[0].lLbound=0;psa=SafeArrayCreate(VT_R8,1,rgsabound);//(3).放置数据元素到SafeArray:for(longindex=0;index<=uIsRead;index++) { SafeArrayPutElement(psa,&index,&bVal[index]);}//(4).封装到VARIANT内: varChunk->vt=VT_R8; varChunk->parray=psa;//(5)读取SafeArray中的数据的步骤:DOUBLEbuf[10];for(longind=0;ind<10;ind++) { ::SafeArrayGetElement(pvar.parray,&ind,buf+ind); }doubledou=0;for(longi=0;i<10;i++){ dou=buf[i];}