为什么override和final标识符具有特殊含义而不是保留关键字?

30
C++11中添加了override specifierfinal specifier。它们与其他添加到C++11的指定符(如constexprdecltype)不同,因为它们不是关键字,因此可以用作标识符。请注意保留HTML标签。
int main()
{
  int override = 0 ;    // Ok
  int final = 0 ;       // Ok
  //int constexpr = 0 ; // Error
}

这些被称为具有特殊含义的标识符,在C++11标准草案第2.11[lex.name]中进行了解释(强调我的):

表3中的标识符在特定上下文中具有特殊含义。在语法中引用这些标识符时,显式使用这些标识符而不是使用标识符语法生成。对于给定标识符是否具有特殊含义的任何歧义都将解决为将令牌解释为常规标识符。

表3 -- 具有特殊含义的标识符列出了overridefinal

为什么这两个限定符最终成为具有特殊含义的标识符而不是关键字


1
我认为你之前已经确定了重新定义具有特殊含义的标识符是未定义行为,对吗? - Cory Kramer
@CoryKramer 这是关于 #define 的。不过 @Shafik 可能需要澄清一下这个问题。 - T.C.
我认为正确的问题应该是相反的:为什么有这么多单词首先成为关键字。 - user541686
1
这里有一个相关的问题(但不是重复的):为什么C++11中“override”在最后? - TonyK
@TonyK 感谢您指向那个问题。我不知道我是怎么错过你在答案中提到的那篇博客文章的,尽管我做了很多搜索,但我还是花了一段时间才找到 N3163 - Shafik Yaghmour
显示剩余3条评论
1个回答

35
添加新关键字很难,因为它会从用户的标识符中删除。这最终是在选择潜在破坏当前使用标识符的旧代码的标识符或选择那些高度不可能破坏旧代码但丑陋或与其使用方式不相关的名称之间进行权衡。
在这种特定情况下,overridefinal最终被用于语法中不允许出现用户标识符的位置。因此,在这些位置上,标识符可以具有特殊含义,并且在这些上下文之外,它们可以被视为常规标识符,使得它们可供用户使用。自2005年以来,《C++/CLI》一直在使用这种技术,称为上下文敏感关键字,这在C++/CLI标准9.1.1节“标识符”中有所涉及。
我们可以在N3163: Override Control Using Contextual Keywords中看到一份报告,其中讨论了添加支持虚拟控制属性的不同方法的权衡。它讨论了三种选择:使用[[attributes]],这被认为是不可取的原因包括它们只是伪装成关键字(从下面的论文中修改的示例)。
  • Using contextual keywords, where the keyword has a special meaning only in certain contexts. This was deemed to be the best option.

  • Using operator overloading, which was also deemed undesirable for reasons including that it is difficult to specify a syntax that conveys the intended meaning without introducing ambiguity.

  • class A : public B {
      virtual void f [[override]] () { ... }
      virtual void h [[final]] () { ... }
    };
    
  • 使用保留关键字,这可能会破坏现有的代码,除非选择 不美观的名称以下为修改后的论文示例):

    class A : public B {
      virtual void f override_func () { ... }
      virtual void h final_func () { ... }
    };
    
  • 使用上下文相关的关键字,这不会破坏现有代码,并允许使用“漂亮的名称”(改编自下面论文的例子):

    class A : public B {
      virtual void f() override { ... }
      virtual void h() final { ... }
    };
    
    以下是论文中关于使用上下文敏感的关键词而不是其他两种选择的论点(强调我的观点):
    “在Rapperswil做出了这样的观察,这种方法可能会使错误恢复和语法高亮更加困难。例如,语法高亮稍微有些困难,因为你需要解析以知道标识符是否位于具有特殊含义并应该突出显示的位置。但这并不是特别困难,尤其不是与我们在C++中已经比其他语言要做的更困难的事情相比。

    这对于几个编译器作者来说只是一些小不便,但对用户来说却是无缝的。这是正确的折衷方案。否则,拥有丑陋的全局保留名称(选项2)或不适当和明显的附加属性(选项1)可能会使几个编译器作者在一周内感到轻松,但数百万用户将永远生活在这些问题中。

    这些更改是通过N3206: Override control: Eliminating AttributesN3272: Follow-up on override control应用于标准的。

  • 网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接