在 C++ Builder 和 VC++ 中使用 std::string 的差异
Differences using std::string in C++ Builder and VC++
因为我可以买到新的RAD Studio Xe4,我想我会试一试。不幸的是,我对C++没有经验,因此我想知道为什么在VC++中运行良好的代码在C++生成器中根本不起作用。大多数问题是转换不同的变量类型。例如:
std::string Test = " ";
GetFileAttributes(Test.c_str());
在VC ++中工作,但在C++生成器中它无法编译,告诉我"E2034无法将'const char *'转换为'wchar_t *'。我错过了什么吗?在所有编译器上的工作方式不同的原因是什么?谢谢
欢迎来到 Windows Unicode/ASCII 地狱。
函数
GetFileAttributes
实际上是一个定义为GetFileAttributesA
或GetFileAttributesW
的宏,具体取决于您在包含 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 执行此操作。
- cppcheck在const std::string[]上引发警告
- 将std::string传递给WriteConsole API
- 为std::string的某个索引赋值
- 使用 std::string () const 函数启动线程或未来
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 如何更改大小(std::string)
- std::string 的对象真的可以移动吗?
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 无法从 std::string 中提取C++ Unicode 符号
- std::string 构造函数如何处理固定大小的 char[]?
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 将C++ std::string 转换为 UTF-16-LE 编码的字符串
- 重载 + 自己的类和 std::string 的运算符
- 如何使用 std::string 作为 QHash 的键?
- 将日语 wstring 转换为 std::string
- 可以从std::string继承以提供类型一致性吗
- 构造函数采用std::string_view与std::string并移动
- 在共享缓冲区内存中创建 ::std::string 对象
- std::string.size() 未知行为
- Valgrind 在 std::string::swap 中报告 SIGILL