我有这个严重的问题。我在2个名称空间中有一个枚举,如下所示:
namespace FANLib {
namespace ERROR {
enum TYPE {
/// FSL error codes
FSL_PARSER_FILE_IERROR,...
和我的代码中的其他地方,我这样使用它:
FANLib::Log::internalLog(FSLParser::FILE_IERROR, file_ierror, true, FANLib::ERROR::FSL_PARSER_FILE_IERROR);
所有编译都很好,但如果我碰巧包含“windows.h”,我会收到错误!问题出在“WinGDI.h”中,其中包含以下行:
#define ERROR 0
并使编译器认为,在FANLib :: ...之后,有一个零! 我得到的错误是:
错误1错误C2589:'常数':'::'
右侧的非法令牌错误2错误C2059:语法错误:'::'
错误3错误C2039:'FSL_PARSER_FILE_IERROR':不是'`global namespace''的成员
我有什么办法可以解决这个问题,而不必因为一些不经意的#define
而改变我的命名空间吗?我在另一篇文章中读过我可以#undef ERROR,但这有多安全?
答案 0 :(得分:14)
通常,您应该避免使用全大写标识符,因为它们用于宏。在这种情况下,我将重命名命名空间。
(作为旁注,<windows.h>
#define
其他内容如GetPrinter
,实际上它很烦人。我通常会使用#undef
。这也有助于在.cpp文件中包含<windows.h>
,并确保标题所影响的范围尽可能小。)
答案 1 :(得分:2)
重命名命名空间是最干净,最安全,最具互操作性的解决方案。
答案 2 :(得分:2)
跳过“重命名你的命名空间”的潮流,只是因为ERROR
过于普遍而且含糊不清。找一些更具描述性的东西。
答案 3 :(得分:1)
我认为如果你#undef它不会有问题。但是,你必须在使用你的枚举和放大器的任何地方都这样做。 WINDOWS.H。最好的方法是重命名你的命名空间。
答案 4 :(得分:1)
您可能希望重构代码,以便只在必要时显示#include。 “正确”的方式甚至可能涉及制作单独的文件和标题,其中包含您将从windows.h调用的函数的接口
但是,如果您只是想要一个简单的修复并关注#undef ERROR的副作用,只需在完成声明后重新定义ERROR:
#undef ERROR namespace ERROR { #define ERROR 0
每次引用ERROR时都必须这样做(而不是在字符串中)。
话虽如此,如果您只是未定义错误,那么您应该没问题。它只会影响C预处理器从那时起如何处理ERROR(或者更确切地说是如何处理)。
顺便说一句,我一般都看到所有大写字母的名字只用于指定常量,而不是用于类型和命名空间。如果我是你,我会重新考虑我的命名惯例。
答案 5 :(得分:0)
最好的解决方案是更改您的命名方案以避免全部大写,正如其他人所建议的那样:
namespace FANLib {
namespace Error {
enum Type {
/// FSL error codes
FSL_Parser_File_IError, ...
也是禁止限制:以_或__开头的标识符。 (它比这更复杂,但是如果你只是避免使用以下划线开头的所有名字,你的生活会更简单。)
答案 6 :(得分:0)
如果您不使用GDI,那么您可以定义NOGDI
来禁止在WinGDI.h中定义宏。 Here您可以找到其他有用的选项。
答案 7 :(得分:0)
以E开头的标识符或数字或E和大写字母应视为保留,因为这些新的宏可以添加到<errno.h>
。