In my writing, I discussed the nature of the Varaint type in detail in ATL (iv)--variant and CComVariant, and explained in detail why CComVariant could be a complete substitute for varaint, I'm going to explain the BSTR and CComBSTR in detail, but unlike Varaint and CComVariant, CComVariant is a subclass of Varaint, and when passing parameters, it is the concept of the subclass object Is-a the parent class. Are the BSTR and ccombstr the same kind of relationship? No! Let's first look at the definition of a BSTR:
typedef OLECHAR __RPC_FAR *bstr;
typedef WCHAR OLECHAR;
typedef wchar_t WCHAR;
typedef unsigned short wchar_t;
Through this series of macro definitions, you can clearly see the nature of the BSTR, it is not a struct, not a class, but a few layers of the built-in data type vest, from which we can also assert that the CComBSTR class is certainly not a child of a BSTR, How can the CComBSTR be the perfect substitute for a BSTR? Let's just take a look at the definition of CComBSTR, and honestly, these codes are really like artwork.
CComBSTR
Class CComBSTR
{
Public
BSTR m_str;
CComBSTR ()
{
M_str = NULL;
}
CComBSTR (int nSize)
{
M_STR =:: SysAllocStringLen (NULL, nSize);
}
CComBSTR (int nSize, LPCOLESTR sz)
{
M_STR =:: SysAllocStringLen (SZ, nSize);
}
CComBSTR (Lpcolestr PSRC)
{
M_STR =:: SysAllocString (PSRC);
}
CComBSTR (const ccombstr& SRC)
{
M_STR = src. Copy ();
}
CComBSTR (refguid src)
{
LPOLESTR Szguid;
Stringfromclsid (SRC, &szguid);
M_STR =:: SysAllocString (SZGUID);
CoTaskMemFree (SZGUID);
}
ccombstr& operator= (const ccombstr& SRC)
{
if (m_str! = src.m_str)
{
if (M_STR)
:: SysFreeString (M_STR);
M_STR = src. Copy ();
}
return *this;
}
ccombstr& operator= (lpcolestr pSrc)
{
:: SysFreeString (M_STR);
M_STR =:: SysAllocString (PSRC);
return *this;
}
~ccombstr ()
{
:: SysFreeString (M_STR);
}
unsigned int Length () const
{
return (m_str = = NULL)? 0:sysstringlen (M_STR);
}
operator BSTR () const
{
return m_str;
}
bstr* operator& ()
{
Return &m_str;
}
BSTR Copy () const
{
Return:: SysAllocStringLen (M_STR,:: Sysstringlen (M_STR));
}
HRESULT CopyTo (bstr* pbstr)
{
Atlassert (pbstr! = NULL);
if (pbstr = = NULL)
return e_pointer;
*PBSTR =:: SysAllocStringLen (M_STR,:: Sysstringlen (M_STR));
if (*pbstr = = NULL)
return e_outofmemory;
return S_OK;
}
void Attach (BSTR src)
{
Atlassert (m_str = = NULL);
M_STR = src;
}
BSTR Detach ()
{
BSTR s = m_str;
M_str = NULL;
return s;
}
void Empty ()
{
:: SysFreeString (M_STR);
M_str = NULL;
}
BOOL operator! () const
{
return (m_str = = NULL);
}
HRESULT Append (const ccombstr& BSTRSRC)
{
Return Append (Bstrsrc.m_str, Sysstringlen (BSTRSRC.M_STR));
}
HRESULT Append (LPCOLESTR lpsz)
{
Return Append (Lpsz, Ocslen (lpsz));
}
A BSTR is just a lpcolestr so we need a special version to signify
That we is appending a BSTR
HRESULT appendbstr (BSTR p)
{
Return Append (P, Sysstringlen (p));
}
HRESULT Append (lpcolestr lpsz, int nlen)
{
int n1 = Length ();
BSTR b;
b =:: SysAllocStringLen (NULL, N1+nlen);
if (b = = NULL)
return e_outofmemory;
memcpy (b, M_str, n1*sizeof (Olechar));
memcpy (B+n1, Lpsz, nlen*sizeof (Olechar));
B[n1+nlen] = NULL;
SysFreeString (M_STR);
M_str = b;
return S_OK;
}
HRESULT ToLower ()
{
Uses_conversion;
if (m_str! = NULL)
{
LPTSTR psz = Charlower (ole2t (M_STR));
if (psz = = NULL)
return e_outofmemory;
BSTR B = t2bstr (PSZ);
if (psz = = NULL)
return e_outofmemory;
SysFreeString (M_STR);
M_str = b;
}
return S_OK;
}
HRESULT ToUpper ()
{
Uses_conversion;
if (m_str! = NULL)
{
LPTSTR psz = Charupper (ole2t (M_STR));
if (psz = = NULL)
return e_outofmemory;
BSTR B = t2bstr (PSZ);
if (psz = = NULL)
return e_outofmemory;
SysFreeString (M_STR);
M_str = b;
}
return S_OK;
}
BOOL LoadString (hinstance hInst, UINT NID)
{
Uses_conversion;
TCHAR sz[512];
UINT Nlen =:: LoadString (HInst, NID, SZ, 512);
Atlassert (Nlen < 511);
SysFreeString (M_STR);
M_STR = (Nlen! = 0)? SysAllocString (T2ole (SZ)): NULL;
Return (Nlen! = 0);
}
BOOL LoadString (UINT NID)
{
Return LoadString (_pmodule->m_hinstresource, NID);
}
ccombstr& operator+= (const ccombstr& BSTRSRC)
{
Appendbstr (BSTRSRC.M_STR);
return *this;
}
BOOL operator< (BSTR bstrsrc) const
{
if (BSTRSRC = = NULL && M_STR = = null)
return false;
if (bstrsrc! = NULL && M_STR! = null)
Return wcscmp (M_STR, BSTRSRC) < 0;
return m_str = = NULL;
}
BOOL operator== (BSTR bstrsrc) const
{
if (BSTRSRC = = NULL && M_STR = = null)
return true;
if (bstrsrc! = NULL && M_STR! = null)
Return wcscmp (m_str, bstrsrc) = = 0;
return false;
}
BOOL operator< (LPCSTR pszsrc) const
{
if (PSZSRC = = NULL && M_STR = = null)
return false;
Uses_conversion;
if (pszsrc! = NULL && M_STR! = null)
Return wcscmp (M_str, a2w (pszsrc)) < 0;
return m_str = = NULL;
}
BOOL operator== (LPCSTR pszsrc) const
{
if (PSZSRC = = NULL && M_STR = = null)
return true;
Uses_conversion;
if (pszsrc! = NULL && M_STR! = null)
Return wcscmp (M_str, a2w (pszsrc)) = = 0;
return false;
}
#ifndef Ole2ansi
CComBSTR (LPCSTR PSRC)
{
M_str = A2wbstr (PSRC);
}
CComBSTR (int nSize, LPCSTR sz)
{
M_STR = A2wbstr (sz, nSize);
}
void Append (LPCSTR lpsz)
{
Uses_conversion;
Lpcolestr LPO = A2cole (lpsz);
Append (LPO, Ocslen (LPO));
}
ccombstr& operator= (LPCSTR pSrc)
{
:: SysFreeString (M_STR);
M_str = A2wbstr (PSRC);
return *this;
}
#endif
HRESULT WriteToStream (istream* pStream)
{
Atlassert (PStream! = NULL);
ULONG CB;
ULONG Cbstrlen = m_str? Sysstringbytelen (M_STR) +sizeof (Olechar): 0;
HRESULT hr = Pstream->write ((void*) &cbstrlen, sizeof (Cbstrlen), &CB);
if (FAILED (HR))
return HR;
Return Cbstrlen? Pstream->write ((void*) m_str, Cbstrlen, &CB): S_OK;
}
HRESULT ReadFromStream (istream* pStream)
{
Atlassert (PStream! = NULL);
Atlassert (m_str = = NULL); should be empty
ULONG Cbstrlen = 0;
HRESULT hr = Pstream->read ((void*) &cbstrlen, sizeof (Cbstrlen), NULL);
if ((hr = S_OK) && (Cbstrlen! = 0))
{
Subtract size for terminating NULL which we wrote out
Since SysAllocStringByteLen overallocates for the NULL
M_str = SysAllocStringByteLen (NULL, cbstrlen-sizeof (Olechar));
if (m_str = = NULL)
hr = E_outofmemory;
Else
hr = Pstream->read ((void*) m_str, Cbstrlen, NULL);
}
if (hr = = S_FALSE)
hr = E_FAIL;
return HR;
}
};
I marked the need for attention in red bold, and by the definition of CComBSTR we can see that CComBSTR is a top class, with no complex social backgrounds (such as a lot of inheritance and precompiled directives, etc.), and constructors and assignment operators provide a lot of Basically can satisfy the use of initialization and assignment operations, the most in place of the service is I marked in red bold two functions, one is forced type conversion, through similar operator overloading way to complete, this grammar general beginner is unfamiliar, suggest further study; one is operator overloading on & symbols. These two functions can act as a CComBSTR class and operate a BSTR, which means you can do this, assuming you want to invoke a function that looks like this:
void TEST (BSTR Str1, BSTR *pstr2, BSTR STR3);
Let's say you define a variable like this:
BSTR BSTR;
CComBSTR CoBstr1, COBSTR2;
It is perfectly possible to use COBSTR1 and COBSTR2 as a variant of the BSTR type when calling the test function, as follows:
TEST (BSTR, &COBSTR1, COBSTR2); The call cannot be passed in VC6.0?
What's up, great!
This article is from the "8403723" blog, please be sure to keep this source http://8413723.blog.51cto.com/8403723/1729788
on ATL (vi)--BSTR and CComBSTR class