如何避免与Windows头文件中定义的宏名称冲突?

时间:2010-02-23 21:07:17

标签: c++ windows macros collision

我有一些C ++代码包含一个名为CreateDirectory().的方法。以前代码只使用STL和Boost,但最近我必须包含<windows.h>,所以我可以查找CSIDL_LOCAL_APPDATA

现在,这段代码:

filesystem.CreateDirectory(p->Pathname()); // Actually create it...

不再编译:

error C2039: 'CreateDirectoryA' : is not a member of ...

winbase.h中的此宏对应:

#ifdef UNICODE
#define CreateDirectory  CreateDirectoryW
#else
#define CreateDirectory  CreateDirectoryA
#endif // !UNICODE

预处理器正在重新定义我的方法调用。有没有办法避免这种命名冲突?或者我是否必须重命名CreateDirectory()方法?

8 个答案:

答案 0 :(得分:14)

如果您只是重命名CreateDirectory方法,那将会更好。如果你需要使用Windows API,与Windows.h的战斗是一场失败的战斗。

很明显,如果你在包含windows.h时一致,那么仍然会进行编译。 (虽然你可能在其他地方遇到问题)。

答案 1 :(得分:9)

#undef CreateDirectory

答案 2 :(得分:9)

您可以创建一个模块,其唯一目的是#include <windows.h>并查找包含在函数中的CSIDL_LOCAL_APPDATA。

int get_CSIDL_LOCAL_APPDATA(void)
{
    return CSIDL_LOCAL_APPDATA;
}
顺便说一句,为解决发生的事情做得好!

答案 3 :(得分:1)

作为跨平台代码库的开发人员,这是一个问题。处理它的唯一方法是

  • 确保windows.h至少在Windows上构建 - 普遍包含在内。然后CreateDirectory宏在每个编译单元中定义,并且通常用CreateDirectoryW替换。预编译头文件非常适合此

或者,如果这是一个令人不愉快的主张,(并且它适合我)

  • 将windows.h用法隔离到Windows特定的实用程序文件中。创建导出基本所需功能的文件。头文件必须使用与之兼容但不依赖于包含windows.h的数据类型。 cpp实现文件必须(显然)使用windows.h。

如果您的功能需要包含带有冲突符号的项目头文件,则必须使用以下模式:

#include <windows.h>
#ifdef CreateDirectory
#undef CreateDirectory
#endif
// etc
#include "some_class_with_CreateDirectory_method.h"
// ...

然后你需要显式调用你拥有的任何windows api函数的非宏版本#undef'd - CreateDirectoryA或W等。

答案 4 :(得分:0)

push宏,再次undefpop宏:

#pragma push_macro("CreateDirectory")
#undef CreateDirectory
void MyClass::CreateDirectory()
{
 // ...
}
#pragma pop_macro("CreateDirectory")

答案 5 :(得分:0)

请注意,名称冲突通常来自包含的某个头文件。在此之前,像CreateDirectory和GetMessage这样的东西没有被提升到可见性,代码编译没有问题。

您可以将这样的包含隔离到包装头文件中,并在其末尾隔离“#undef whatever”。然后,无论你有什么名字冲突都会消失。当然,除非您需要在自己的代码中使用这些宏(是的,所以非常可能......)

答案 6 :(得分:0)

您可以备份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

答案 7 :(得分:-2)

#pragma push_macro("CreateDirectory")

如果没有任何效果,您可以使用自己的命名空间代替重命名。