14

I'm trying to see the reason why, in C++11, they had to add the override keyword at the end of the method instead of the beginning like virtual. I don't see the interest of being able to write both virtual and override in the declaration of a method.

Is there a technical reason why the committee didn't choose to simply be able to write override instead of virtual when it was needed?

Thanks!

quantdev
  • 23,517
  • 5
  • 55
  • 88
Creak
  • 4,021
  • 3
  • 20
  • 25
  • 2
    A large part of the problem is that they aren't reserved keywords! That is, you can name your function `override`. This is presumably a backwards compatibility problem. – Bill Lynch Jan 27 '15 at 04:55
  • 2
    Context-sensitive keywords is a new C++11 thing, and introduced fairly late in the standardization process. The previous implementation experience from C++/CLI was to put them at the end and that worked well. – T.C. Jan 27 '15 at 05:21
  • There is no technical reason. They liked it there more because it's just a grammar and you are free to create anything you like for _your_ language. Some even thought it would be so cool to put everything in parentheses (see LISP). – t3chb0t Jan 27 '15 at 06:14
  • Similary you could ask a hundred more questions like: why do we write `class A` and not `A class` or `void foo()` and not not `foo() void` (although we actually do in `VB.NET` LOL). – t3chb0t Jan 27 '15 at 06:20
  • 1
    "I don't see the interest of being able to write both virtual and override" You don't need to. When declaring an overriding function the `virtual` keyword has no effect whatsoever, feel free to leave it out. – Ben Voigt Jan 27 '15 at 16:12
  • I must disagree, this is not opinion based! As explained in a comment below, it's just that most of the time, when I don't understand a decision in C++11 or C++14, there is a perfectly understandable reason why it's done that way instead of the other and I want to understand why. @TonyK gave the answer I wanted to know. I don't know how to remove the "[on hold]" but I find it particularly unfair in this context, *you* have an opinion on the subject, not me or my question. – Creak Jan 28 '15 at 00:35
  • 1
    @t3chb0t please see my answer [here](http://stackoverflow.com/a/30404389/1708801) there was a well thought out rationale for this choice. – Shafik Yaghmour May 29 '15 at 14:33

2 Answers2

14

The proposal for the addition of the keywords controlling override (override/final) , paper N3151 , gives us some insight about this choice (emphasis mine) :

It is preferable to put such virtual control keywords at the end of the declaration so that they don't clash with eg. return types at the beginning of declarations.

[...]

For context-insensitive, normal keywords, it's less important where the keywords are placed because the words are reserved. We could put them at the beginning of declarations or at the end.

During the discussion of attributes, Francis Glassborow pointed out that the beginning of declarations is becoming crowded. If we put the virtual control keywords at the beginning, we can end up with examples like the one below:

struct B
{
   virtual volatile const unsigned long int f()
      volatile const noexcept;
   void f(int g);
};

struct D : B
{
   virtual hides_name virtual_override final_overrider volatile const unsigned long int f()
      volatile const noexcept;
};

Putting the new keywords at the end at least alleviates the situation somewhat:

struct B
{
   virtual volatile const unsigned long int f()
      volatile const noexcept;
   void f(int g);
};

struct D : B
{
   virtual volatile const unsigned long int f()
      hides_name virtual_override final_overrider volatile const noexcept;
};

There are people who think these control keywords should be in the same place with virtual. As mentioned, that place is already crowded.


Note:

The C++ 11 Standard defines context sensitive keywords in section § 2.11 / 2 [lex.name] :

The identifiers in Table 3 have a special meaning when appearing in a certain context. When referred to in the grammar, these identifiers are used explicitly rather than using the identifier grammar production. Unless otherwise specified, any ambiguity as to whether a given identifier has a special meaning is resolved to interpret the token as a regular identifier.

Table3:

final override

quantdev
  • 23,517
  • 5
  • 55
  • 88
  • Thanks, actually I even wonder why keep the `virtual`? We could have `virtual` for the first declaration and `override` for the next ones. Is there a difference between `virtual void f() override` and `void f() override`? – Creak Jan 27 '15 at 04:59
  • 2
    @Creak : C++ allows you to omit `virtual` in derived classes, see this [example](http://coliru.stacked-crooked.com/a/0ace91a038198230), and this [question](http://stackoverflow.com/questions/4895294/c-virtual-keyword-for-functions-in-derived-classes-is-it-necessary) – quantdev Jan 27 '15 at 05:03
  • 1
    I know that. I'm simply trying to challenge the concept. For instance, it would have been simpler to be able to right just that: `override void f()`. You see? – Creak Jan 27 '15 at 05:11
  • But understand that I know the standard won't be changed just because I asked the question ;) I'm simply trying to get the reason why they couldn't do that, because I'm asking this question for a year now and I still have no clue. – Creak Jan 27 '15 at 05:13
  • The C++ designers might try to justify their choice but at the end it's just a design choice. They could have put it everywhere because it's just a grammar and no laws of physics or anything else limit the choices here. Like french or english or german grammars are different so are C++ and C# and Python different although the purpose of all of them is to communicate with (other people or a machine). What matters is what the _framework_ can do for you so why come up with so many different grammars instead of one well designed? I think it's insane. – t3chb0t Jan 27 '15 at 06:08
  • No one really uses `volatile`, do they? – rubenvb Jan 27 '15 at 08:18
  • @Creak : they **could** have done it the other way, they id not based on the arguments here but thats it, and that's a bit opinion based, too. – quantdev Jan 27 '15 at 12:30
  • @quantdev: It's just that most of the time, when I don't understand a decision in C++11 or C++14, there is a perfectly understandable reason why it's done that way instead of the other. Here, it's not just an opinion of mine, there is apparently no good reason why C++11 allows us to have both `virtual` and `override`. – Creak Jan 27 '15 at 23:28
  • I think @TonyK nailed it! ;) – Creak Jan 27 '15 at 23:32
  • [N3163 which I reference in my answer here](http://stackoverflow.com/a/30404389/1708801) is a better reference than `N3151`, IMO. – Shafik Yaghmour May 29 '15 at 14:31
  • The rationale for "override" and "final" to be where they are is clear. What is less clear to me is why "virtual" was not allowed to be put in the same place as well so that we can have a consistent language. – Bruce Adams May 10 '22 at 13:52
11

There certainly is a technical reason for it! You can read all about it in this article.

Briefly, override is a context-sensitive keyword, which means that you can also use it as an identifier. It was done this way to avoid breaking existing code that uses this identifier. That means that it has to appear in a position where identifiers are not allowed, namely immediately after the closing parenthesis of a function declaration.

TonyK
  • 16,761
  • 4
  • 37
  • 72
  • 2
    This isn't a reason but a justification. The parser could be programmed in a way it understands `override` correctly even if it's before the function name. – t3chb0t Jan 27 '15 at 08:33
  • 2
    @t3chb0t: Perhaps you are right. But if `override` and `final` are `typedef`s, it's not obvious to a _human_ how to parse e.g. `virtual override final f();` – TonyK Jan 27 '15 at 08:38
  • The abuse of `typedef` is rather a bad a example ;-] Some time ago there was a similar quesion about what happened if some did this: `#define private public`. It's impossible to prevent everything. The programmer also has to be resposible for what he is writing. If you desire to write code that no one understands then there is no such programming languge grammar that can prevent that ;-) – t3chb0t Jan 27 '15 at 08:44
  • @t3chb0t: I think we are agreed that the context-dependency rules are simpler this way. Let's just leave it at that. – TonyK Jan 27 '15 at 09:14
  • @t3chb0t `typedef` is fundamentally different from the preprocessor. You are comparing two very different things. – Zyx 2000 Jan 27 '15 at 12:26
  • @Zyx2000 It wasn't my intention to compare it. I just meant an abuse of the avaliable constructs like in TonyK's example where other _types_ or _words_ replace some known _keywords_ and confuse the programmer. It's about whether it is possible or resonable to prevent such code by creating a weird grammar. – t3chb0t Jan 27 '15 at 12:30
  • @t3chb0t: The point is that in the case of `override` it's not really abuse (at least from a language perspective). C++98/03 did *not* say `override` was reserved in any way. It's just an ordinary identifier that programmers were free to use as they saw fit. Then, after *years* of allowing it for normal use, the committee decided to give it a special meaning. They valued backward compatibility enough to avoid doing that in a way that would break existing code that already used `override` as a normal identifier. – Jerry Coffin Jan 27 '15 at 18:07
  • @JerryCoffin: Yes. But t3chb0t's point is that they could have _still_ retained compatibility with existing code by allowing `override` before a member function declaration instead of after it. And I agree. So in that sense my answer was overly simplistic -- the point is that allowing `override` before a function declaration would have made the context-dependency rules more complicated and harder to implement. – TonyK Jan 27 '15 at 18:12
  • @TonyK: But if you allowed it there, and and `override` was already defined as a type, which meaning would you attach to it? If you wanted a function to return an override and also wanted to mark it as overriding, would that be `override override f()`? – Jerry Coffin Jan 27 '15 at 18:16
  • @Jerry: Yes. The first `override` is the context-dependent keyword, and the second `override` is the return type. Like I said, it's a bit more complicated that way. – TonyK Jan 27 '15 at 18:35
  • @TonyK: it's a lot more than "a bit more complicated that way". It *might* be possible, but C++ is already extremely difficult to parse, and this would add not just more complexity, but entire *new* and different complexity. I'd have to write out a grammar (and at least part of a parser) to be sure it can be parsed unambiguously at all. – Jerry Coffin Jan 27 '15 at 18:59
  • @JerryCoffin: It seems we are in agreement here. – TonyK Jan 27 '15 at 19:29
  • @JerryCoffin: You must admit that it's a shame that it was chosen to have a more complex language over a parsing implementation issue. `virtual` and `override` are of the same "family", as a developer stand point, a method is either one or the other (`override` implying that it's virtual of course). In a long term view, I don't expect all the future developers to know all the history of C++ in order to understand the language peculiarities. – Creak Jan 27 '15 at 23:41
  • 1
    I'm not sure it really complicates the language a whole lot, but yes, I can see where it would be nice if `override` could be in essentially any position instead of having to be in one specific position. At the same time, you have other things (e.g., noexcept) that are similarly restricted, and even in the original language exception specifications were in the same place. – Jerry Coffin Jan 28 '15 at 00:27