3

有谁知道为什么这个代码根据这个网站是不正确的:

CString First( "John" );
CString Last( "Doe" );

CString Name;

Name.Format( "%s %s", First, Last ); // Name may be garbage text

Name.Format( "%s %s", (LPCSTR)First, (LPCSTR)Last ); // this is the correct way

CString::Format的微软文档说:

...当您将字符串作为可选参数传递时,您必须将其显式转换为 LPCTSTR ...

我总是使用“错误”的方式(没有 LPCSTR 演员)而且我从来没有遇到过问题。

我在这里错过了什么吗?

4

4 回答 4

3

因为在 Format 函数内部没有进行强制转换,就像在指定参数时没有进行强制转换一样printf()

如果您写printf( "%d", a );,则不会进行任何转换,a因为 printf 假设%d已经告诉了数据类型a是什么。

为了确保将CString其转换为LPCSTRie %s,您需要转换参数,该参数将调用CString返回LPCSTR. 在 CString 的更高版本中,字符串被存储,因此当您在没有强制转换的情况下编写时,它仍然会打印为 LPCSTR,但要确保最好进行强制转换。

或者换一种说法:当可变参数函数通过参数时,它使用格式说明符来了解参数的大小,如果格式说明符与参数不匹配,则会得到垃圾。由于 CString 没有格式说明符,因此您需要将 CString 转换为 LPCSTR。

顺便说一句,您应该static_cast<LPCSTR>(First), static_cast<LPCSTR>(Last)在 C++ 中使用

于 2013-01-16T11:39:46.117 回答
2

转换为 LPCSTR 会调用转换运算符operator LPCSTR()(应该是operator const char *().

不调用 LPCSTR 意味着您正在传递整个 CString 对象,然后盲目地使用底层结构的前 32 位或 64 位作为 char 指针。

回顾一下:LPCSTR(str)是调用一个方法来确保正确的行为,str而是盲目的玩弄。

于 2013-01-16T11:45:16.870 回答
1

我认为(抱歉,我现在没有可用的 MFC 来检查)只是出于效率原因才需要强制转换,以避免在参数类型未知时 MFC 必须执行的无用临时复制(CString 在修改时被懒惰地复制) .

诀窍是 CString 内存分配之前 this为缓冲区(TCHAR *)以外的一些基本数据保留空间,例如引用计数器。

然后,当您按值将 CString 传递给可变参数函数时,它会“看到”缓冲区(指针)强制转换“提取”只是缓冲区,而不调用复制构造函数。

于 2013-01-16T12:10:37.693 回答
1

因为如果您使用子类 CString 参数,它会中断。

于 2013-01-17T01:28:44.407 回答