VARIANT是一个联合结构体,完整的定义为:
typedef 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;
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;
为方便操作,定义了另外一个类_variant_t,完整定义为:
class _variant_t : public ::tagVARIANT {
public:
// Constructors
//
_variant_t() throw();
_variant_t(const VARIANT& varSrc) ;
_variant_t(const VARIANT* pSrc) ;
_variant_t(const _variant_t& varSrc) ;
_variant_t(VARIANT& varSrc, bool fCopy) ; // Attach VARIANT if !fCopy
_variant_t(short sSrc, VARTYPE vtSrc = VT_I2) ; // Creates a VT_I2, or a VT_BOOL
_variant_t(long lSrc, VARTYPE vtSrc = VT_I4) ; // Creates a VT_I4, a VT_ERROR, or a VT_BOOL
_variant_t(float fltSrc) throw(); // Creates a VT_R4
_variant_t(double dblSrc, VARTYPE vtSrc = VT_R8) ; // Creates a VT_R8, or a VT_DATE
_variant_t(const CY& cySrc) throw(); // Creates a VT_CY
_variant_t(const _bstr_t& bstrSrc) ; // Creates a VT_BSTR
_variant_t(const wchar_t *pSrc) ; // Creates a VT_BSTR
_variant_t(const char* pSrc) ; // Creates a VT_BSTR
_variant_t(IDispatch* pSrc, bool fAddRef = true) throw(); // Creates a VT_DISPATCH
_variant_t(bool boolSrc) throw(); // Creates a VT_BOOL
_variant_t(IUnknown* pSrc, bool fAddRef = true) throw(); // Creates a VT_UNKNOWN
_variant_t(const DECIMAL& decSrc) throw(); // Creates a VT_DECIMAL
_variant_t(BYTE bSrc) throw(); // Creates a VT_UI1
_variant_t(char cSrc) throw(); // Creates a VT_I1
_variant_t(unsigned short usSrc) throw(); // Creates a VT_UI2
_variant_t(unsigned long ulSrc) throw(); // Creates a VT_UI4
_variant_t(int iSrc) throw(); // Creates a VT_INT
_variant_t(unsigned int uiSrc) throw(); // Creates a VT_UINT
#if (_WIN32_WINNT >= 0x0501)
_variant_t(__int64 i8Src) throw(); // Creates a VT_I8
_variant_t(unsigned __int64 ui8Src) throw(); // Creates a VT_UI8
#endif
// Destructor
//
~_variant_t() throw() ;
// Extractors
//
operator short() const ; // Extracts a short from a VT_I2
operator long() const ; // Extracts a long from a VT_I4
operator float() const ; // Extracts a float from a VT_R4
operator double() const ; // Extracts a double from a VT_R8
operator CY() const ; // Extracts a CY from a VT_CY
operator _bstr_t() const ; // Extracts a _bstr_t from a VT_BSTR
operator IDispatch*() const ; // Extracts a IDispatch* from a VT_DISPATCH
operator bool() const ; // Extracts a bool from a VT_BOOL
operator IUnknown*() const ; // Extracts a IUnknown* from a VT_UNKNOWN
operator DECIMAL() const ; // Extracts a DECIMAL from a VT_DECIMAL
operator BYTE() const ; // Extracts a BTYE (unsigned char) from a VT_UI1
operator VARIANT() const throw();
operator char() const ; // Extracts a char from a VT_I1
operator unsigned short() const ; // Extracts a unsigned short from a VT_UI2
operator unsigned long() const ; // Extracts a unsigned long from a VT_UI4
operator int() const ; // Extracts a int from a VT_INT
operator unsigned int() const ; // Extracts a unsigned int from a VT_UINT
#if (_WIN32_WINNT >= 0x0501)
operator __int64() const ; // Extracts a __int64 from a VT_I8
operator unsigned __int64() const ; // Extracts a unsigned __int64 from a VT_UI8
#endif
// Assignment operations
//
_variant_t& operator=(const VARIANT& varSrc) ;
_variant_t& operator=(const VARIANT* pSrc) ;
_variant_t& operator=(const _variant_t& varSrc) ;
_variant_t& operator=(short sSrc) ; // Assign a VT_I2, or a VT_BOOL
_variant_t& operator=(long lSrc) ; // Assign a VT_I4, a VT_ERROR or a VT_BOOL
_variant_t& operator=(float fltSrc) ; // Assign a VT_R4
_variant_t& operator=(double dblSrc) ; // Assign a VT_R8, or a VT_DATE
_variant_t& operator=(const CY& cySrc) ; // Assign a VT_CY
_variant_t& operator=(const _bstr_t& bstrSrc) ; // Assign a VT_BSTR
_variant_t& operator=(const wchar_t* pSrc) ; // Assign a VT_BSTR
_variant_t& operator=(const char* pSrc) ; // Assign a VT_BSTR
_variant_t& operator=(IDispatch* pSrc) ; // Assign a VT_DISPATCH
_variant_t& operator=(bool boolSrc) ; // Assign a VT_BOOL
_variant_t& operator=(IUnknown* pSrc) ; // Assign a VT_UNKNOWN
_variant_t& operator=(const DECIMAL& decSrc) ; // Assign a VT_DECIMAL
_variant_t& operator=(BYTE bSrc) ; // Assign a VT_UI1
_variant_t& operator=(char cSrc) ; // Assign a VT_I1
_variant_t& operator=(unsigned short usSrc) ; // Assign a VT_UI2
_variant_t& operator=(unsigned long ulSrc) ; // Assign a VT_UI4
_variant_t& operator=(int iSrc) ; // Assign a VT_INT
_variant_t& operator=(unsigned int uiSrc) ; // Assign a VT_UINT
#if (_WIN32_WINNT >= 0x0501)
_variant_t& operator=(__int64 i8Src) ; // Assign a VT_I8
_variant_t& operator=(unsigned __int64 ui8Src) ; // Assign a VT_UI8
#endif
// Comparison operations
//
bool operator==(const VARIANT& varSrc) const throw();
bool operator==(const VARIANT* pSrc) const throw();
bool operator!=(const VARIANT& varSrc) const throw();
bool operator!=(const VARIANT* pSrc) const throw();
// Low-level operations
//
void Clear() ;
void Attach(VARIANT& varSrc) ;
VARIANT Detach() throw();
VARIANT& GetVARIANT() throw();
VARIANT* GetAddress() ;
void ChangeType(VARTYPE vartype, const _variant_t* pSrc = NULL) ;
void SetString(const char* pSrc) ; // used to set ANSI string
};
通常的操作方法为,使用VARIANT定义变量,使用 _variant_t 初始化变量值。
但给类成员变量赋值字符串值时会有问题。
例如:
class A{
public;
VARIANT m_var;
}
A a;
a.m_var = _variant_t(“1234”);
这种情况下,m_var中存放的是个野指针,实际的指针在_variant_t的析构函数中被释放了。
如果是其他类型的数据,这种赋值方式是没问题的。
正确的做法应该是这样的:
m_var.vt=VT_STR;
m_var.bstrVal=SysAllocString("1234");
考虑代码的严谨性,整个类应该这样设计:
class A{
public;
VARIANT m_var;
A::A()
{}
A::A(LPCTSTR str)
{
VariantInit(&m_var);
m_var.vt = VT_BSTR;
m_var.bstrVal=SysAllocString(str);
}
A::~A()
{
if (m_var.vt = VT_BSTR)
{
SysFreeString(m_var.bstrVal);
}
VariantClear(&m_var);
}
}