在 C++ Builder 和 VC++ 中使用 std::string 的差异

Differences using std::string in C++ Builder and VC++

本文关键字:std string Builder C++ VC++      更新时间:2023-10-16

因为我可以买到新的RAD Studio Xe4,我想我会试一试。不幸的是,我对C++没有经验,因此我想知道为什么在VC++中运行良好的代码在C++生成器中根本不起作用。大多数问题是转换不同的变量类型。例如:

std::string Test = " ";
GetFileAttributes(Test.c_str());

在VC ++中工作,但在C++生成器中它无法编译,告诉我"E2034无法将'const char *'转换为'wchar_t *'。我错过了什么吗?在所有编译器上的工作方式不同的原因是什么?谢谢

欢迎来到 Windows Unicode/ASCII 地狱。

函数

GetFileAttributes

实际上是一个定义为GetFileAttributesAGetFileAttributesW的宏,具体取决于您在包含 Windows 标头时是否定义了_UNICODE(或者是否UNICODE,还是两者兼而有之?*A变体采用char*和相关参数,*W函数采用wchar_t*和相关参数。

我建议在新代码中仅调用宽*W变体。这意味着切换到 std::wstring 仅用于 Windows 代码和一些经过深思熟虑的跨平台应用程序设计选择。

C++生成器配置设置为使用 UNICODE 字符集,这意味着 Win32 API 解析为其宽字符版本。因此,您需要在C++代码中使用宽字符字符串。如果将 VS 配置设置为使用 UNICODE,则会收到相同的错误。

你可以试试这个:

// wstring = basic_string<wchar_t>
// _T macro ensures that the specified literal is a wide char literal
std::wstring Test = _T(" ");     
GetFileAttributes(Test.c_str()); // c_str now returns const wchar_t*, not const char* 

在此处查看有关_T/_TEXT宏的更多详细信息:http://docwiki.embarcadero.com/RADStudio/XE3/en/TCHAR_Mapping

您已在 Builder 中定义了_UNICODE和/或UNICODE,但未在 VC 中定义它。

大多数 Windows API 都有 2 种风格:ANSI 风格和 UNICODE 风格。

因为,当你调用SetWindowText时,实际上没有SetWindowText函数。相反,有2种不同的功能- SetWindowTextA 它接受 ANSI 字符串和- SetWindowTextW 它采用 UNICODE 字符串。

如果您的程序是使用/DUNICODE/D_UNICODE 编译的,则SetWindowText映射到 SetWindowTextW which expects a const wchar_t *'。

如果您的程序在未定义这些宏的情况下编译,它将映射到需要const char * SetWindowTextA

窗口标头通常会执行类似操作来实现此目的。

#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif 

同样,有 2 GetFileAttributes .

DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName);
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName);

在VC中,你还没有定义UNICODE/_UNICODE,因此你可以传递返回char * string::c_str()

在 Builder 中,您可能已经定义了 UNICODE/_UNICODE 并且它需要一个wchar_t *

您可能没有明确地完成此 UNICODE/_UNICODE 操作 - 可能是 IDE 正在为您执行此操作 - 因此请检查 IDE 中的选项。

您有很多方法可以解决此问题

  • 在 IDE 中找到 UNICODE/_UNICODE 选项并将其禁用。

  • 使用 std::w_string - 则c_str()将返回wchar_t *

  • 直接调用GetFileAttributesA而不是GetFileAttributes - 您需要为这 2 个变体附带的所有其他 Windows API 执行此操作。