为啥我需要这个 CString 类型转换?
Posted
技术标签:
【中文标题】为啥我需要这个 CString 类型转换?【英文标题】:Why do I need this CString type cast?为什么我需要这个 CString 类型转换? 【发布时间】:2012-04-17 20:47:17 【问题描述】:我已将字符串移动到资源中,幸运的是,我有 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 才能完成这项工作?
【问题讨论】:
【参考方案1】:您的IDS_MY_STRING
并不是真正的指向字符串的指针。它是一个整数。 (如果它是一个字符串指针,那么您一开始就不需要 LPCTSTR
强制转换。)CString
知道如何从完整的资源 ID 加载资源字符串。
MessageBox
没有;它需要一个真正的字符指针,CString
隐式提供。
【讨论】:
【参考方案2】:真正的问题(或至少答案中有趣的部分)不是关于第二个如何失败,而是更多关于第一个如何工作。
第一个有效,因为 CString 的构造函数接受 LPCSTR 实际上会查看该值以确定它是否真的是指向字符串的指针,还是字符串资源的标识符。在后一种情况下,它会自动加载字符串资源并创建具有相同内容的 CString。 IOW,您已经获得了从字符串标识符到 CString 的隐式转换。
CString 还支持隐式转换为 LPCSTR/LPCSTR/LPCWSTR。
然而,C++ 只会进行一个 用户定义的隐式转换,以从传递给表达式所需的任何类型中获取任何类型。在这种情况下,要从字符串 ID 到 LPCTSTR
,您需要两个 - 一个从字符串 ID 到 CString
,另一个从 CString
到 LPCTSTR
。编译器不会自动为您执行此操作。
因此,要将字符串 ID 转换为 LPCTSTR
,您需要将字符串 ID 显式转换为 CString
,它使用 CString
的构造函数,该构造函数采用 LPCTSTR
。因此,您将字符串 ID 转换为 LPCTSTR
,然后将其转换为 CString
,这将创建一个 CString
。然后编译器会自动为您从CString
转换为(真正的)`LPCTSTR。
【讨论】:
你的最后一段有点混乱。我想你想说的是我们仍然需要从string ID
到CString
的转换。比 CString 隐式转换为 LPCTSTR。通过输入(CString) (LPCTSTR)
,我们正在进行从ID 到CString 的一次转换。
写CString((LPCTSTR)IDS_MY_STRING)
而不是两个显式转换不是更易读吗?
@ChristianAmmer:是的,我可能会那样做。【参考方案3】:
其他人已经解释了类型转换等的细节。
此外,为了简化您的代码,您可能需要#define
一个方便的宏,如下所示:
#define _S(id) (CString(LPCTSTR(id)))
然后将其与MessageBox
一起使用(或用于其他LPCTSTR
参数):
MessageBox( hWnd, _S(IDS_MY_STRING), _S(IDS_TITLE), MB_RETRYCANCEL );
【讨论】:
【参考方案4】:MessageBox
没有采用资源 ID 的重载,但您可以改用 AfxMessageBox
。
【讨论】:
以上是关于为啥我需要这个 CString 类型转换?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在java 8中转换类型的reduce方法需要一个组合器