CAtlString是可以在ANSI和UNICODE之间转换的,例如CAtlStringA strSomething = lpszSomething,这里的lpszSomething是wchar_t字符串类型。
可是你会发现这种语句有时候可以编过,有时候又不可以编过,非要用CAtlStringA strSomething(lpszSomething):
error C2440: 'initializing' : cannot convert from 'PCTSTR' to 'ATL::CStringT<BaseType,StringTraits>'
with
[
BaseType=char,
StringTraits=ATL::StrTraitATL<char,ATL::ChTraitsCRT<char>>
]
Constructor for class 'ATL::CStringT<BaseType,StringTraits>' is declared 'explicit'
with
[
BaseType=char,
StringTraits=ATL::StrTraitATL<char,ATL::ChTraitsCRT<char>>
]
遇到这种问题真是抑郁,明知是2B的问题却不明真相,每次遇到只能退缩改为显式构造。
这次深究了一下,CAtlString的实现会落在CStringT上,CStringT的构造函数对于YCHAR(即另一种字符类型,CStringT把自身的字符类型定义为XCHAR)作参数如下:
CSTRING_EXPLICIT CStringT( __in_z_opt const YCHAR* pszSrc )
注意这里有个CSTRING_EXPLICIT宏,它被定义为:
#ifdef _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
#define CSTRING_EXPLICIT explicit
#else
#define CSTRING_EXPLICIT
#endif
原来是有_ATL_CSTRING_EXPLICIT_CONSTRUCTORS宏定义的时候不同类型的字符串转换需要显式调用构造函数,看看stdafx.h里还真有这个宏定义:
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
删掉这个宏定义就能使用CAtlStringA strSomething = lpszSomething这类用法了。为什么需要这么一个宏去控制这类构造函数需要显式调用?
MS说得很清楚了,防止无心的字符串转换。_ATL_CSTRING_EXPLICIT_CONSTRUCTORS