我已将字符串移至资源中,幸运的是,我有 LPCTSTR 运算符可以方便地实例化字符串,例如:
CString str( (LPCSTR) IDS_MY_STRING);
现在我想使用 MessageBox() 进行类似的类型转换,因此它也从资源中加载字符串,所以我这样做:
MessageBox( hWnd, (LPCTSTR) IDS_MY_STRING ,"Error", MB_RETRYCANCEL);
但这不起作用,它可以编译但在运行时崩溃。现在以下内容可以工作:
MessageBox( hWnd, (CString) (LPCTSTR) IDS_MY_STRING ,"Error", MB_RETRYCANCEL);
我的问题是 MessageBox() 无论如何都将 LPCTSTR 作为第二个参数,那么为什么我们必须额外从 LPCTSTR 类型转换为 CString 才能完成这项工作?
真正的问题(或者至少是答案中有趣的部分)不是关于第二个问题如何失败,而是更多关于第一个问题如何工作。
第一个之所以有效,是因为
CString
的构造函数采用 LPCTSTR
实际上会查看该值来确定它是否真的是指向字符串的指针,或者字符串资源的标识符。在后一种情况下,它会自动加载字符串资源并创建具有相同内容的 CString
。 IOW,您将获得从字符串标识符到 CString
的隐式转换。
CString
还支持隐式转换为 LPCTSTR
/LPCSTR
/LPCWSTR
。
然而,C++ 只会执行一个用户定义的隐式转换,以从传递的任何类型转换为表达式所需的任何类型。在这种情况下,要从字符串 ID 到 LPCTSTR
,您需要两个 - 一个从字符串 ID 到 CString
,另一个从
CString
到
LPCTSTR
。编译器不会自动为您执行此操作。
因此,要从字符串 ID 转换为
LPCTSTR
,您需要显式地从字符串 ID 转换为 CString
,这使用
CString
的构造函数(采用
LPCTSTR
)。因此,您将字符串 ID 转换为
LPCTSTR
,然后再转换为
CString
,这将创建一个
CString
。然后编译器会自动为您从
CString
转换为(真实的)
LPCTSTR
。您的
LPCTSTR
转换。)
CString
知道如何从完整资源 ID 加载资源字符串。
MessageBox
没有;它需要一个真正的字符指针,CString
隐式提供了它。其他人已经解释了类型转换等细节
#define
#define _S(id) (CString(LPCTSTR(id)))
然后将其与 MessageBox
一起使用(或也用于其他 LPCTSTR
参数):
MessageBox( hWnd, _S(IDS_MY_STRING), _S(IDS_TITLE), MB_RETRYCANCEL );
AfxMessageBox
代替。