Tag Archives: contrapositive

A Place for Override, and Every Override in its Place

“I love C++!”, said an enthusiastic job candidate during an interview a year ago.  That candidate has since become one of the best developers I ever hired.  I too love C++, and especially so during its current renaissance.  Prior to C++11, the last time I felt this way was at the 1997 Visual C++ Developers Conference in Orlando.  Here, C++98 improvements like explicit and mutable were unveiled, causing many a developer to run back to their ARM to review “const correctness”, which had more or less been ignored to that point.  If C++98 was evolutionary, C++11 is revolutionary – a tour de force of new features.  Some, like lambdas, are bold forays into the archrival territory of functional programming.  The most profound new feature, from my perspective, is Rvalue References.  These enable move semantics (construction and assignment), which are potentially far more efficient than their copy counterparts.  For a language that lacks access to the compiler’s parse tree, features like Rvalue References permit surprisingly subtle expressions for optimal code generation.

So the C++ language is alive and well, and its priesthood is openly solicitous of new ideas from the community.  I’ll oblige with a series of posts on features I’d like to see added to the language.  Each of these has been born of necessity, when in the throes of a coding session I lamented that I had to once again resort to workarounds.

To kick things off, let’s consider override.   This new keyword (strictly, an “identifier”, but I’ll use “keyword” for simplicity and clarity) allows the programmer to make a distinction between an override of an existing virtual method, and the introduction of a new virtual method.  Previously, the keyword virtual was overloaded for this purpose and often led to errors when virtual dispatching would fail due to a refactoring of base or derived classes.  Let’s see how this could happen.

Initially the code looks like this:

struct Base
{
	virtual void foo()
	{
		cout << "Base::foo called" << endl;
	}
};

struct RiskyDerived : public Base
{
	// "virtual" is optional, making overrides difficult to track down
	void foo()
	{
		cout << "RiskyDerived::foo called" << endl;
	}
};

RiskyDerived derived;
Base & base = derived;
base.foo();	// "RiskyDerived::foo called"

After a hasty refactor, we now have this:

struct Base
{
	virtual void foo(int = 0)
	{
		cout << "Base::foo called" << endl;
	}
};

RiskyDerived derived;
Base & base = derived;
base.foo(); // "Base::foo called"

The binding of BrokenDerived::foo to the vtable entry of Base::foo is now broken, but the code still compiles, resulting in a runtime error (the worst kind).  But with the override keyword in place, we are protected from situations like this because the compiler will issue an error:

struct BetterDerived : public Base
{
	// Error: member function declared with 'override' does not override a base class member
	void foo() override;
};

The problem with override is that it’s only a half solution.  My development team has been bit by the situation above on a number of occasions.  So naturally, when a new keyword like override is introduced, we eagerly embrace it and look for a way to systematically employ it throughout the codebase.  That’s where override breaks down.  In its current implementation, systematic use is not feasible, because the keyword is optional.

What we have today is this behavior:

All uses of the override keyword must in fact override a virtual method. 

What we’re lacking is a way to enforce the contrapositive:

If a virtual method lacks the override keyword, it must not override a virtual method. 

We might term the current behavior “weak” or “permissive”, and my ideal behavior “strong” or “strict”.  In “strict” mode, without the override keyword, a method declaration must either introduce:

  1. A new virtual method (if accompanied by the virtual keyword) or
  2. A new non-virtual method, possibly hiding or overloading another method of the same name.

In short, all virtual method overrides must use the override keyword in “strict” mode.

I understand that a “strict override” would be a breaking change to much existing code.  But that is the whole point:  I would like the compiler to tell me where I need to use override (or not).  Because the virtual keyword is optional when declaring an overridden virtual method, it is a tedious and error prone exercise to manually track down all appropriate locations for override in an existing codebase.   It’s true that some compilers will warn of method hiding, if the signature alone changes.  But if the name of the method changes, the compiler is silent as the grave.

In “strict” mode, on the other hand, our hypothetical compiler could issue a warning such as this:

struct BestDerived : public Base
{
	// Warning: member function overrides a base class member, but is not declared with 'override'
	void foo();
};

Perhaps this is best left as a compiler extension, due to the concern over breaking changes.  But it surprises me that no compiler, to my knowledge, currently offers it.  At a minimum, as a user of Microsoft’s compiler, it seems to me that a third-party tool could be created that scans the Intellisense database to determine “strict override” violations.  Any takers?  Visual Assist team?