刚刚抓到了一个愚蠢的错误。我有一个带有CreateFile()
函数的 zip 处理库。Winbase.h
,包含在我的标题深处的某个地方,重新定义它CreateFileW
并且链接器发疯了。
当然,我会winbase
在这种特殊情况下排除。它首先不应该在范围内。但是理论上的问题还是很有趣的,
有没有办法在本地压制一些定义?
刚刚抓到了一个愚蠢的错误。我有一个带有CreateFile()
函数的 zip 处理库。Winbase.h
,包含在我的标题深处的某个地方,重新定义它CreateFileW
并且链接器发疯了。
当然,我会winbase
在这种特殊情况下排除。它首先不应该在范围内。但是理论上的问题还是很有趣的,
有没有办法在本地压制一些定义?
您可以通过在名称周围加上括号来绕过宏:
(CreateFile)(arguments);
这是有效的,因为宏CreateFile
是一个类似函数的宏(即它接受括号中的参数列表);名称后面的右括号与使用类函数宏的语法不匹配,因此预处理器不会扩展它。
当然,“正确”的解决方案是正确命名函数,即create_file
.<g>
预处理器宏没有 C++ 范围的概念。#define
s 只是文本替换。如果你想拥有一个 'local' #define
,你可以这样做:
#define CreateFileW CreateFile
... // here I can use the macro
#undef CreateFileW
或者在你的情况下
#undef CreateFileW
... // Here the macro is not available
#define CreateFileW CreateFile
删除有问题的头文件始终是解决此问题的最佳解决方案(尤其是与windows.h
or一样大的头文件winbase.h
- 它们在许多项目中被包含得太自由了)。
唯一的其他解决方案是#undef offending_symbol
.
当然,另一个重要的事情是“不要使用与 Windows/Linux 系统调用名称匹配的名称”——但是CreateFile
对于创建文件的函数来说,这是一个非常明显的名称,因此我可以看到诱惑。
有
#undef
它删除了定义(但没有别的)。
除了上述之外,从#undef
技术上讲,您对 s 无能为力#define
,至少不可移植。
最好的方法是根本不使用#define
,或者至少尽可能少使用并且尽可能受到限制。有时你只需要一个宏来生成一些样板代码几次。完成后请务必使用#undef
该宏。我能想到的唯一其他有效应用#define
包括用于条件预处理的警卫和标志。
对于#define
像 WinAPI 标头这样的问题,您应该尽可能地限制它们。不要#define
在标题中使用该 API 的 d 类型。您几乎从不想在整个应用程序中使用 API,因此只能在 API 周围一小层的 cpps 中使用它。以这种方式减少依赖关系不仅仅是对代码的其余部分进行消毒。