7

I've always wondered about the decision, why override and final has to be after member-function declarator:

struct Base {
    virtual void virtFun();
};
struct Foo: Base {
    virtual void virtFun() override;
};

For me, it would be more logical to put override/final in place of virtual:

struct Base {
    virtual void virtFun();
};
struct Foo: Base {
    override void virtFun();
};

Is there a reason behind this? Maybe some compatibility issue with pre C++11?

geza
  • 28,403
  • 6
  • 61
  • 135
  • You *can* write `virtual void virtFun() override` too – Justin Nov 02 '17 at 22:20
  • Given that "override" is a new keyword, I can't think of any technical reason why. Whoever thought up the "override" keyword, decided that's where it belongs, completely arbitrarily. No special reason for that. – Sam Varshavchik Nov 02 '17 at 22:21
  • @Justin two specifiers in `virtual void virtFun() override` are redundant because `override` implies that method is `virtual`. – user7860670 Nov 02 '17 at 22:21
  • 2
    Strongly related to [Why are override and final identifiers with special meaning instead of reserved keywords?](https://stackoverflow.com/q/30404388/1708801) ... `override and final end up being used in the grammar in places where no user identifiers can appear. So in those places the identifiers can have a special meaning and outside of those contexts they can be treated as a regular identifier leaving the identifiers available for users. ` – Shafik Yaghmour Nov 02 '17 at 22:23
  • @SamVarshavchik They aren't keywords, they're "identifiers with a special meaning." To work reliably, this requires them to appear where arbitrary identifiers cannot. See the question linked by Shafik Yaghmour. – Angew is no longer proud of SO Nov 02 '17 at 22:25
  • It's hard to make new keywords. People are always already using the word you wanted to use. – user4581301 Nov 02 '17 at 22:28
  • 1
    @ShafikYaghmour tl;dr; it is basically a trickery to maintain compatibility with pre C++11 code, just like op guessed. So language syntax became even less consistent than it was before. I think the better idea would be to require compilers to issue a warning when name collision between some identifier and "specifies" as a first step and then make those "specifiers" a proper reserved keywords. – user7860670 Nov 02 '17 at 22:32
  • 1
    A decent term for this is "contextual keyword", it only means something when it appears in the right place. And the compiler only treats it specially when it knows enough about the context of the statement. Having it at the end of the statement makes all the difference, the parser already has a pretty good idea that you are writing a function declaration, so doesn't need the kind of help that a keyword provides. Compare to Java which went through the same evolution, they have to write `@Override`. That @ is butt-ugly, but does allow it to appear at the start of the declaration. – Hans Passant Nov 02 '17 at 22:48
  • @HansPassant: yep, @ is ugly. My solution would have been to forbid `override` or `final` as a type-name. These are unlikely type-names in the first place. Just because of this, we have these specifiers in a wrong place. The benefits of using override/final as a type-name is much lower than allowing to put override/final to the place where they belong. We use `override`/`final` as a type-name much more rarely (*almost never*) then we use them to specify an overridden/final method (*all the time*). – geza Nov 02 '17 at 22:56

1 Answers1

18

It's because override and final are not keywords.

Instead they are special identifiers.

That means you can actually declare variables, functions or type-names (type-alias or classes) with those names.

They can only be used like member-function modifiers in a very small context, where the context have to be know beforehand by the compiler as it parses the source. Placing them after the function declaration is a very simple way of removing ambiguity from the C++ grammar for that context.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    Which means that if they were at the position of `virtual`, you'd have some problems: `final myFunction();` is a function returning the `final` datatype. At the very least, allowing `final` / `override` in that position would complicate the grammar, but it may be possible to be ambiguous – Justin Nov 02 '17 at 22:24
  • Thanks for the answer! But, they could have been special identifiers at the place of virtual, don't they? There, only types can be, it doesn't seem to be that difficult. With this, variables, functions still can be specified with these names, only types could not be. – geza Nov 02 '17 at 22:28
  • @geza The problem is that these names *could* be used for type-names as well. You could even define a *class* with the name `override`. Not allowing certain names for certain categories of identifiers is a very slippery slope down a rabbit hole. – Some programmer dude Nov 02 '17 at 22:41
  • Okay :) `override` or `final` is not a likely type-name. For me, the benefits of override/final at the place of virtual is much more higher than I cannot use them as type-names. But now I understand the decision behind this, but I don't agree with it. – geza Nov 02 '17 at 22:45
  • @geza Introducing new keywords can break a lot of existing code (and for this reason is a very high-hurdle to jump in the standardisation process). So this is a compromise. If they were added as keywords any existing program with `override` or `final` in it would fail to compile and the proposer of the change would have to "cost-justify" the potential breaking change(s) to the standard. – Richard Critten Nov 02 '17 at 23:34
  • @RichardCritten: yes, I understand that. I'm not talking about keywords, it could have been just reserved type-names. I understand, that this could break existing code too, but not too many. And even, fixing them should be easy in a lot of cases. And it is not forbidden to create new keywords, `constexpr` is a new one. Yes, it is unlikely that `constexpr` causes much trouble, but forbidding final/override as a type-name shouldn't have caused too much trouble either. Anyways, the decision is already made, there's no point to argue about this too much. – geza Nov 02 '17 at 23:57