Explicit Overrides

• 4 min read

::: {dir="ltr" style="text-align: left;" trbidi="on"} In the last two days, I have been twice bitten by the loose nature of legacy C++ language.

I had developed a base class that abstracts the core features of a module a year back. The class itself was a great success. Since developing it for a specific module, I successfully refactored another module to use this and was able to do so in a relatively short window of 1 week. This is the background.

Recently, I had an opportunity to re-use this class for another module and having been successful earlier twice, I guess I was a little callous in using it without referring to the accompanied documentation. The design requires that I override a bunch of methods and admittedly I was as little cocky -- if I had designed and implemented it earlier, it should be a snap for me to re-use it. So I wrote the code, compiled it, removed a few syntax errors and dropped it into test. All good, except that couple of overridden methods were not being invoked!

WTF? It also so happened that the callback to the overridden methods were triggered by an external event. Off I went tracing this path to see what's going on. Nothing wrong there either. WTF??

With nowhere else left to investigate, I went back to the base class design. And it was then that I realized the rather embarrassing mistake that I had made. I guess the code is perhaps worth a thousand words -- so here it goes.

Base class implementation:

class Base {
protected:
   virtual void onInitialize();
   virtual void onShutdown(bool fGraceful);
};

And here's the derived class:

class Derived : public Base {
protected:
   virtual void onInitialize();
   virtual void onShutdown();
};

Note the mistake? I had forgotten about the bool fGraceful parameter to onShutdown() and as a result it was defined as a new method in the derived class!

This is precisely the kind of problem that explicit overrides feature in C++11 allows you to evade. If you have a conforming compiler (I didn't), you can declare the derived class as

class Derived : public Base {
protected:
   virtual void onInitialize() override;
   virtual void onShutdown() override;
};

What the trailing override does is to inform the compiler that onShutown() is a method that is overridden from its namesake in the base class. And the compiler, seeing that the prototype for the method in derived class doesn't match what's in the base, would raise an error which would allow you to spot the problem and fix it, even when you're overconfident and cocky!

As for me, I don't have the luxury of using a C++11 compiler and have to live with the possibility that I will make these mistakes again! :::