Is there any point in using `override` when overriding a pure virtual function?
Asked Answered
D

4

62

For example:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function() override;
};

From what I read, the override keyword is used to make sure that we have the correct signature in the function that we are overriding, and it seems to be its only use.

However, in the case of a pure virtual function, the compiler would throw an error if we used an incorrect signature in the Derived class (or Base class, depending on how one see things). So, is there any point in adding override at the end of Derived::my_function() declaration?

Don answered 27/9, 2017 at 11:22 Comment(4)
Note that abstractness propagates. If you provide the wrong signature in the Derived class then the Derived class becomes abstract as well. That might not be detected in the correct place without the override keyword.Zlatoust
It ensures that if the base class changes incompatibly with the override assertion, your code won't compile.Redintegration
"penning purposefully pedagogical programs propagates prefered programming practices" - T.J.ElganBodily
Minor benefit to adding it is that some IDEs will use it as the highlight point to show implementations or to jump to the parent.Machute
H
95

However, in the case of a pure virtual function, the compiler would throw an error if we used an incorrect signature in the Derived class

No, this compiles:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int);
//                 ^^^ mistake!
};

While this does not:

class Base {
  virtual void my_function() = 0;
};

class Derived : Base {
  void my_function(int) override;
};

error: void Derived::my_function(int) marked override, but does not override


The error you're talking about only occurs when instantiating Derived - override allows you to catch the mistake earlier and makes the definition of Derived clearer/more readable.

Housebreaking answered 27/9, 2017 at 11:24 Comment(12)
You could add in a runtime bug with another class, and implementing Base::my_function while leaving it pure virtual.Scarberry
wait so there is a point? You go on to talk about how it is useful but start out with just "no".Draper
The "No" is in response to the claim that the compiler throws an error.Wineglass
Why does that member function definition count as an override in a way that satisfies the compiler? Isn’t the signature not compatible with the base function signature?Lm
@Lm thats the point, a programmer puts override when they believe the signature they are writing should appear exactly in a base class. The first case is a mistake because the programmer intended to override the function, but accidentally wrote an overload instead.Unmeaning
@SteveCox Perhaps I'm missing something, but if that's an overload, why would this code compile? Wouldn't the pure virtual function prevent the code from linking?Lm
@Lm Compile-time errors are better than link-time errors.Goering
@AndreKostur That's true - but to confirm, you couldn't fully build and run the first bit of code, right?Lm
@Lm I'd rather not wait for the build system to have to work it's way though compiling all of the rest of my project and waiting until it tried to link it all together to only have it finally fail. (Or fail somewhere else when you tried to instantiate a Derived...) It would be much nicer to have it fail when compiling that one file, and have it point to exactly that line and have it say "This line right here is wrong".Goering
@AndreKostur Oh, certainly. I read the part about the code compiling and didn't realize that it meant literally "compiling, but not linking," and was worried I was missing something about the language.Lm
Does a missing override elicit a compiler warning if the function indeed does override a base class function, possibly unintentionally? That would be another reason to consistently use it: Prevent accidental overriding.Abohm
This could be an especially vile problem if Base and Derived are part of a library, and Derived is only intended for the library's clients but never instantiated by the library itself. In such case, this wouldn't even be a link-time error, but either a test failure or (in absence of testing) a delivered bug.Prototype
J
37

Yes, it is a good idea to use override keyword consistently as a defensive practice.

Consider a redesign when the author of the Base decides that my_function should no longer be a pure virtual, and also that it should take a new parameter. With override in place the compiler will catch this problem; without an override your Derived class would continue to compile.

Jayejaylene answered 27/9, 2017 at 11:27 Comment(0)
S
11

Yes !!

It improves code clarity: override keyword prevents ambiguity and convey it's meaning of overriding its base class method.

Prevents possible unintended usage: In future, if base class change method signature(here virtual) , it force derive class to change accordingly. (with compiler error). Otherwise(with-out override keyword ) it could be considered method overload, which is not intended.

Sldney answered 27/9, 2017 at 13:11 Comment(1)
it wouldn't be method overload because of hiding normally, thoughBarlow
S
3

Usually not bothering with override just moves an error around. I find the location where you get the error better -- at the point where you define the method that fails to override, instead of when you instantiate the class.

But, there is a way for this to protect against a runtime bug.

struct Base {
  virtual void foo(int x = 0) = 0;

  void foo(double d) {
      foo( (int)d );
  }
};
inline void Base::foo(int x) { std::cout << "Default foo(" << x << ")\n"; }

struct Derived:Base {
  using Base::foo;
  virtual void foo() { // oops, no int!
    std::cout << "Derived::foo()\n";
    Base::foo();
  }
};
struct Derived2:Derived {
  virtual void foo(int x=0) override {
    std::cout << "Derived2::foo()\n";
    Derived::foo(x);
  }
};

here we intend for each foo to call its parent foo. But because Derived::foo doesn't override the same signature as Base::foo, it isn't invoked.

Add override after foo() in Derived and we get a compile time error.

And yes, I implemented the pure virtual function Base::foo.

Scarberry answered 27/9, 2017 at 13:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.