对问题Disable check for override in gcc的回答建议在命令行上使用-Doverride=
来禁用错误使用override的错误,这实际上与添加相同:
#define override
到源文件。
我最初的反应是,这似乎是未定义的行为,因为我们正在重新定义关键字,但查看草案C ++ 11标准部分2.12
关键字[lex.key] 我是很惊讶,覆盖和最终都不是关键字。它们在上一节2.11
[lex.name] 中有所介绍,它们说它们是具有特殊含义的标识符:
表3中的标识符出现在a中时具有特殊含义 某些背景[...]
和表3 标记为具有特殊含义的标识符,包括覆盖和最终。
问题是,重新定义(使用#define )具有特殊含义的标识符是未定义的行为吗?在这方面,它们与关键字的处理方式有何不同?
答案 0 :(得分:12)
如果您使用的是C ++标准库,则未定义的行为是重新定义具有特殊含义的标识符,这也适用于关键字。从17.6.4
[constraints] 部分的C ++ 11标准草案中,我们有17.6.4.1
[constraints.overview] 部分,其中说:
本节介绍对使用C ++程序的C ++程序的限制 C ++标准库的设施[...]
在17.6.4
下,我们有17.6.4.3.1
[macro.names] 部分,其中包含:
翻译单位不得在词汇上定义#define或#undef 与关键字相同,与表3中列出的标识符相同,或与 7.6中描述的属性标记。
表3 列出具有特殊含义的标识符。我们可以看到此段落还涵盖了关键字,并且它们也以相同的方式处理。
答案 1 :(得分:1)
实现'标准头文件允许"实现"在宏可以满足函数要求的情况下使用宏的标准函数(包括确保参数只被评估一次)。此外,允许这样的宏使用其行为在标准中指定的关键字或标识符,或者保留给实现&#34 ;;在重新定义关键字或标识符的上下文中使用此类宏可能会产生任意影响。
话说回来,对这种形式的UB的历史解释就是说编制者不应该不顾一切地导致古怪的行为,并且在迂腐模式之外"应该允许用户代码将含义分配给编译器否则不会使用的保留标识符。如果代码既可以在需要关键字__packed
的编译器上使用,也可以在既不识别也不需要这样的关键字的编译器上使用,则这可能很有用。)以您正在做的方式重新定义关键字有点笨拙;它可能会起作用,但它很可能会破坏标准库宏的行为。