为什么我需要这个 CString 类型转换?

问题描述 投票:0回答:4

我已将字符串移至资源中,幸运的是,我有 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 才能完成这项工作?

c++ mfc
4个回答
4
投票

真正的问题(或者至少是答案中有趣的部分)不是关于第二个问题如何失败,而是更多关于第一个问题如何工作。

第一个之所以有效,是因为

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

您的

3
投票
并不是真正指向字符串的指针。它是一个整数。 (如果它是一个字符串指针,那么您首先就不需要

LPCTSTR

 转换。) 
CString
 知道如何从完整资源 ID 加载资源字符串。
MessageBox

没有;它需要一个真正的字符指针,

CString

隐式提供了它。

其他人已经解释了类型转换等细节

1
投票
此外,为了简化代码,您可能需要

#define

一个像这样方便的宏:

#define _S(id) (CString(LPCTSTR(id))) 

然后将其与
MessageBox
一起使用(或也用于其他

LPCTSTR

 参数):
MessageBox( hWnd, _S(IDS_MY_STRING), _S(IDS_TITLE), MB_RETRYCANCEL );


1
投票
没有获取资源 ID 的重载,但您可以使用

AfxMessageBox

 代替。

© www.soinside.com 2019 - 2024. All rights reserved.