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

Why do I need this CString type cast?

本文关键字:CString 类型转换 为什么      更新时间:2023-10-16

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

你的IDS_MY_STRING并不是一个指向字符串的指针。它是一个整数。(如果它是一个字符串指针,则从一开始就不需要LPCTSTR强制转换。 CString知道如何从整型资源 ID 加载资源字符串。

MessageBox不需要;它需要一个真正的字符指针,CString隐式提供。

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

第一个工作是因为 CString 的构造函数采用 LPCSTR 实际上查看值以确定它是否真的是指向字符串的指针,还是字符串资源的标识符。在后一种情况下,它会自动加载字符串资源并创建具有相同内容的 CString。IOW,您已经获得了从字符串标识符到 CString 的隐式转换。

CString 还支持隐式转换为

LPCSTR/LPCSTR/LPCWSTR。

但是,C++只会执行一个用户定义的隐式转换,以从传递的任何类型获取表达式所需的任何类型。在这种情况下,要从字符串 ID 获取到LPCTSTR,您需要两个 - 一个从字符串 ID 到 CString,另一个从CStringLPCTSTR。编译器不会自动为您执行此操作。

因此,要从字符串 ID 获取到LPCTSTR,需要显式地从字符串 ID 转换为 CString,这使用 CString 的构造函数,该构造函数需要LPCTSTR。因此,您将字符串 ID 强制转换为 LPCTSTR ,并从该 转换为 CString ,这将创建一个CString。然后编译器会自动从CString转换为(真正的)LPCTSTR。

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

此外,为了简化代码,您可能需要#define一个方便的宏,如下所示:

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

然后将其与MessageBox一起使用(或用于其他LPCTSTR参数):

MessageBox( hWnd, _S(IDS_MY_STRING), _S(IDS_TITLE), MB_RETRYCANCEL );
MessageBox 没有

占用资源 ID 的重载,但您可以改用AfxMessageBox