为什么override出现在成员声明之后而不是与virtual相同的位置?

6

我很好奇为什么新的C++11关键字override被强制要求在方法声明之后以与const一致的方式出现,而不是virtual

class SomeBaseClass {
    virtual void DoPolymorphicBehavior() = 0;
    ...
class SomeDerrivedClass : public SomeBaseClass {
    void DoPolymorphicBehavior() override;
    ...

为什么不允许在完全相同的位置(甚至代替)virtual中使用它?
class SomeBaseClass {
    virtual void DoPolymorphicBehavior() = 0;
    ...
class SomeDerrivedClass : public SomeBaseClass {
    override void DoPolymorphicBehavior();
    ...

这样可以让我在源代码中轻松地搜索和替换派生类以利用新关键字,并从编译器中获得帮助以查找错误。然而,由于C++11在语法上将其放置在不同的位置,因此我必须手动更新成千上万行的源代码才能从新的编译器功能中获益。
这个选择肯定有充分的理由吧?

我想了解其中的原因,如果有的话(肯定会有的)。如果有更好的地方可以询问,请指引方向... - Mordachai
2
我不知道是谁投票关闭这些语言设计问题的。如果有有效的理由,而 OP 不知道,那么听到这些理由可能会很有趣。如果没有,那么这可能是一个随机决定或者基于个人口味的决定,这也是一个答案。别告诉我没有人知道委员会真正想要什么,因为有足够多的人知道。+1,我之前没有考虑过这个替代方案。 - Christian Rau
3个回答

11

函数名前出现的声明符序列可以包含标识符(例如,函数的返回类型)。想象一下某些现有代码具有 override 的返回类型:

override foo();

或者甚至是一个名为override的变量:

int override;

介绍一个新的关键字override会破坏任何包含标识符override的现有代码,因为关键字是保留的。因此,他们引入了一个上下文关键字:override(以及final)。上下文关键字是通过其语法位置来识别关键字。在程序中仍然可以有名为overridefinal的标识符。如果这些标识符出现在函数声明的参数列表后面,则具有特殊含义。因此,它被放置在函数参数后面的原因是,引入新的关键字将破坏旧代码,如果编译器在这里看到override,它们知道它的确切含义,因为没有其他标识符可以出现在这里。

我还要补充一点,把它放在函数后面可以清楚地表明重要的是函数而不是返回类型。他们已经遇到了const的问题,被迫将其放在函数后面以避免与返回类型限定符混淆。 - Morwenn
他们在虚拟方面有问题吗?不,我认为这是计划外演变的不幸结果。如果有人从头开始设计C++(比如C#、Java等),他们会把限定符放在前面,因为这更符合可读性和人类思维方式。将const作为后修饰符始终是一个不幸的选择/来自C的遗留问题。在我的看法中,使override和final遵循这种模式是由于向后兼容性而必要的恶,而不是某种设计天才的体现。 - Mordachai
@Mordachai 考虑到形容词在英语中放在名字前面,我同意在函数前面加限定词更符合理解。在我看来,这更多是关于自然语言而非人类思维的问题。在我的母语法语中,形容词通常放在名词后,对于限定词也是如此。既然大多数编程语言使用英语,所以这更像是一个向后兼容的问题,而不是设计演变的问题。 - Morwenn
啊,是的,文化色眼镜。如果它们一直保持一致,我会少些困扰。但是虚拟在很多声明之前,const在很多声明之前或之后,只有在成员函数之后才能使用,i在e之前除了c之后等等还有上千个例外。但你说得对,这并不是“人类思维”级别的普适性,只是英语或其他语言倾向于在名词/主语之前放置形容词/修饰语。 :) - Mordachai

7

它不是一个关键字,这也是你问题的答案。

它是一个在某些上下文中具有特殊含义的标识符。如果允许它出现在声明的开头,可能会与用户定义的返回类型名称产生歧义。


@Mordachai 一个上下文关键字 - Praetorian
那就是推理的原因:为了避免引入一个关键字,它被作为上下文关键字,这意味着它必须出现在方法声明之后? - Mordachai
@Mordachai:简而言之,是的。 - CB Bailey

2
因为overridefinal不是关键字,而是符号,可以出现在用户代码中(例如您可以有一个变量int override;)。它们只在有限的上下文中具有特定的含义,并且这些上下文必须被选择为与用户定义的符号不能出现的上下文相对应。同时,希望立即清楚地表明这一点;例如:
override void DoSomething();

override无法成为用户符号,因为没有语法产生式可以以用户定义的符号开头,后跟void语句。但是,直到编译器遇到void,问题才变得不清楚,如果您有一个用户定义的类型而不是void,它甚至更加模糊不清。另一方面,在函数的参数声明后,上下文是清晰的,编译器的扫描程序立即知道该做什么。


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