如何避免与 Windows 头文件中定义的宏的名称冲突?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2321713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I avoid name collision with macros defined in Windows header files?
提问by Mike Willekes
I have some C++ code that includes a method called CreateDirectory().
Previously the code only used STL and Boost, but I recently had to include <windows.h>
so I could look-up CSIDL_LOCAL_APPDATA
.
我有一些 C++ 代码,其中包含一个名为CreateDirectory().
以前的代码只使用 STL 和 Boost,但我最近不得不包含<windows.h>
这样我可以查找CSIDL_LOCAL_APPDATA
.
Now, this code:
现在,这段代码:
filesystem.CreateDirectory(p->Pathname()); // Actually create it...
No longer compiles:
不再编译:
error C2039: 'CreateDirectoryA' : is not a member of ...
Which corresponds to this macro in winbase.h
:
对应于 中的这个宏winbase.h
:
#ifdef UNICODE
#define CreateDirectory CreateDirectoryW
#else
#define CreateDirectory CreateDirectoryA
#endif // !UNICODE
The pre-processor is redefining my method call. Is there any possible way to avoid this naming collision? Or do I have to rename my CreateDirectory()
method?
预处理器正在重新定义我的方法调用。有没有办法避免这种命名冲突?还是我必须重命名我的CreateDirectory()
方法?
采纳答案by John Knoeller
You will be better off if you just rename your CreateDirectory method. If you need to use windows APIs, fighting with Windows.h is a losing battle.
如果你只是重命名你的 CreateDirectory 方法,你会更好。如果您需要使用 Windows API,与 Windows.h 的斗争是一场失败的战斗。
Incidently, if you were consistentin including windows.h, this will still be compiling. (although you might have problems in other places).
顺便说一句,如果您在包含 windows.h 时保持一致,这仍然会被编译。(尽管您可能在其他地方遇到问题)。
回答by quamrana
You could create a module whose sole purpose is to #include <windows.h>
and look up CSIDL_LOCAL_APPDATA wrapped in a function.
您可以创建一个模块,其唯一目的是#include <windows.h>
查找封装在函数中的 CSIDL_LOCAL_APPDATA。
int get_CSIDL_LOCAL_APPDATA(void)
{
return CSIDL_LOCAL_APPDATA;
}
btw, Well done for working out what happened!
顺便说一句,很好地解决了发生的事情!
回答by rerun
#undef CreateDirectory
#undef 创建目录
回答by Chris Becke
As a developer working on a cross platform codebase, this is a problem. The only way to deal with it is to
作为在跨平台代码库上工作的开发人员,这是一个问题。处理它的唯一方法是
- ensure that windows.h is - on Windows builds at least - universally included. Then the CreateDirectory macro is defined in every one of your compilation units and is universally substituted with CreateDirectoryW. Precompiled headers are ideal for this
- 确保 windows.h 是 - 至少在 Windows 构建上 - 普遍包含。然后 CreateDirectory 宏在您的每个编译单元中定义,并普遍替换为 CreateDirectoryW。预编译头文件非常适合于此
OR, if that is an unpleasant proposition, (and it is for me)
或者,如果这是一个令人不快的提议,(对我来说)
- isolate windows.h usage into windows specific utility files. Create files that export the basic required functionality. The header files must use data types that are compatible with, but do NOT depend on the inclusion of windows.h. The cpp implementation file must (obviously) use windows.h.
- 将 windows.h 的使用隔离到 Windows 特定的实用程序文件中。创建导出基本所需功能的文件。头文件必须使用兼容的数据类型,但不依赖于 windows.h 的包含。cpp 实现文件必须(显然)使用 windows.h。
If your utlility functions need to include project header files with conflicting symbols then the following pattern is a necessity:
如果您的实用程序需要包含具有冲突符号的项目头文件,则必须使用以下模式:
#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...
You will need to then explicitly call the non macro version of any windows api functions you have #undef'd - CreateDirectoryA or W etc.
然后,您将需要显式调用您拥有 #undef 的任何 Windows api 函数的非宏版本 - CreateDirectoryA 或 W 等。
回答by Amir Saniyan
push
macro, undef
it and pop
the macro again:
push
宏,undef
它和pop
宏再次:
#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
// ...
}
#pragma pop_macro("CreateDirectory")
回答by Zeks
Note that name conflict usually comes from a certain header file being included. Until then stuff like CreateDirectory and GetMessage isn't pulled into visibility and code compiles without a problem.
请注意,名称冲突通常来自包含的某个头文件。在那之前,像 CreateDirectory 和 GetMessage 这样的东西不会被拉入可见性,并且代码编译没有问题。
You can isolate such an inclusion into a wrapper header file and "#undef whatever" at its end. Then, whatever name collision you have will be gone. Unless, of course, you need to use those macros in your own code (yeah, so verylikely...)
您可以将此类包含隔离到包装器头文件中,并在其末尾添加“#undef 任何内容”。然后,您遇到的任何名称冲突都将消失。当然,除非您需要在自己的代码中使用这些宏(是的,很可能......)
回答by hkBattousai
You can take a back up of CreateDirectory
, then undefine it, and then define it again when you finish your job with you custom one.
您可以备份CreateDirectory
,然后取消定义它,然后在完成自定义工作后再次定义它。
#ifdef CreateDirectory
#define CreateDirectory_Backup CreateDirectory
#undef CreateDirectory
#endif
// ...
// Define and use your own CreateDirectory() here.
// ...
#ifdef CreateDirectory_Backup
#define CreateDirectory CreateDirectory_Backup
#undef CreateDirectory_Backup
#endif
回答by AureliusMarcus
#pragma push_macro("CreateDirectory")
If nothing works, instead of renaming you could use your own namespace for your functions.
如果没有任何效果,您可以为函数使用自己的命名空间,而不是重命名。