我将C++项目从Visual Studio 2005迁移到Visual Studio 2017 Professional,当我在调试和发布模式下构建时,我会收到以下错误:
1.
在调试构建中,当我使用SetWindowTextA时,如下所示,我会收到错误"错误C2039‘SetWindowTextA':不是‘CStatic’的成员
m_status_text.SetWindowTextA(theStr);
m_status_text被声明为CStatic,如下所示:
CStatic m_status_text;
如果我使用SetWindowTextW,它会在Release Build中引发一个错误。
m_status_text.SetWindowTextW(theStr);
当我将其更改为"SetWindowText"时,如下所示,它同时适用于Debug和Release Build。这是正确的方式吗?
m_status_text.SetWindowText(theStr);
据我所知,当我们使用"SetWindowText"时,在Unicode格式中,它将其视为"SetWindowTextW",而对于多字节字符集格式,它将视为"SetWindowTextA"。
但是SetWindowText是如何用于调试和发布版本的呢?
2.
此外,我们可以像在调试构建中那样使用"_fgetts"而不是"fgets"(对于发布构建("fgetws"(对于调试构建(吗?如果我使用"fgts",我会得到以下错误:
charfgets(char,int,FILE*(:无法将参数1从"TCHAR[260]"转换为"char*">
fgets(currDir,MAX_PATH,f); // For release build
fgetws(currDir, MAX_PATH, f); // For Debug build
我可以使用"_tfopen"代替"fopen(用于发布版本("one_answers"_wfopen"(用于调试版本(吗
f=_ fopen(文件名,_T("r"((;
代替
f = fopen(fileName,"r"); // For release build
f = _wfopen(fileName, L"r"); // For Debug build
请帮我一下。
Windows API为每个处理或允许字符串作为参数的函数提供了两种变体:
- UNICODE,通常函数名将以W结尾
- ANSI:函数名称将以A结尾
然后,Windows API为所有这些函数提供了一个通用变体,没有尾随的a或W字母,该变体将映射到上面的一个(a或W(,具体取决于是否定义了UNICODE。
示例:
SetWindowText
映射到:
-SetWindowTextA(如果未定义UNICODE(=>ANSI((
-SetWindowTextW(如果UNICODE定义为(
UNICODE变体将字符串处理为wchar_t*,而ANSI变体将字符串处理为char*。
TCHAR是宏定义的字符类型,它映射到char或wchar_t,具体取决于是否定义UNICODE:
-TCHAR=char如果未定义UNICODE
-TCHAR=wchar_t
对于"现代"Windows应用程序,VS2017默认使用UNICODE模式(这是VC++项目文件的一个选项(,我建议您继续使用,除非您绝对必须支持Windows的旧版本(即98(
使用UNICODE模式,您将使用SetWindowTextW((函数变体(或仅使用SetWindowText(((,并向其传递wchar_t*(或TCHAR*(字符串。
如果您需要在ANSI和UNICODE模式下支持或编译项目,可能需要使用TCHAR类型,但现在很少需要它。
在您的问题中,您似乎混合了两个相互正交的轴:ANSI与Unicode构建,以及Debug与Release构建。
RE#1 ANSI与Unicode函数调用,当您调用MFC类方法时,您应该简单地调用"未修饰">方法名称,例如:
// Note the use of the "undecorated" SetWindowText method call:
m_status_text.SetWindowText(theStr);
// This gave you an error:
// m_status_text.SetWindowTextA(theStr);
这与调试版本和发布版本无关,后者会影响运行时性能等其他方面。事实上,通常在调试构建中,会有更多的代码被编译并检查不变量和其他安全方面,比如确保索引不会跨越安全的数组边界,或者STL容器中迭代器的正确使用,等等。
所有这些额外的调试构建检查往往会产生效率较低的代码,但这些相同的调试检查可以帮助您检测各种错误,在发布更高效的应用程序版本之前,您可以修复这些问题。
但是,同样,这独立于ANSI与Unicode构建模式方面。
RE#2在发布版本和调试版本中使用不同的文件函数:如果真的需要(你确定吗?你实际上想实现什么?(,你可以使用这样的#ifdef
:
#ifdef _DEBUG
// Debug-build specific code
// ...
#else
// Release-build specific code
// ...
#endif
当然,您可以在Debug和Release版本中使用fopen
、_wfopen
和_tfopen
:同样,这些Unicode/MBCS和Debug/Release版本是正交的。
p。S.一般来说,我鼓励您将代码库转移到Unicode,只在Unicode模式下构建(调试Unicode和发布Unicode(。