ImaginativeThinking.ca


A developers blog

What the Heck is the override keyword in C++

By: Brad

Hi Brad, what the heck is the override keyword in C++? I noticed it recently but don’t recall ever seeing it before; what does it do exactly?

C++Pig

The override keyword is new to C++ as of C++11 and does exactly the same thing as the C# keyword by the same name (except in C++ its optional); it annotates a method as being the re-implementation of a parents classes virtual/abstract method. That is it states to the compiler that this method is virtual and that it overrides an existing virtual/abstract method from this classes parent. In C# this is required in order to re-implemented a base virtual method but in C++ its optional as the compiler doesn’t need to know that is what your doing to actually compile but can be quite helpful if it does as I’ll explain below.

Lets take a step back, what am I talking about when I say re-implementation?

In Object Orientated languages we can define a base class with virtual functions (either pure virtual, as in they have no implementation, or abstract as in they have a default implementation) then define derivative child classes which are based off of the base class which provide the implementation or provides new implementation for the virtual functions which allows us to provide new classes which work slightly differently then the base class. Here is an example:

class Shape
{
public:
    Shape() {}
    virtual ~Shape() {}

    virtual double getArea() = 0;
    virtual int getWidth()
    {
        return m_width;
    }
    virtual int getHeight() 
    {
        return m_height;
    }

private:
    int m_width;
    int m_height;
};


class Rectangle : public Shape
{
public:
    Rectangle() {}
    virtual ~Rectangle() {}

    virtual double getArea() 
    {
         return m_width * m_height;
    }
};


class Square: public Shape
{
public:
    Square() {}
    virtual ~Square() {}

    virtual double getArea() 
    {
         return m_width * m_width;
    }
    virtual int getHeight() 
    {
        return m_width;
    }
};

Above I have three unimaginative and incomplete classes but they do show off this idea of class inherency. I have a base class called Shape which defines an interface for all shape objects. It states that any class which is based off of Shape will have at a minimum three methods getWidth(), getHeight(), and getArea(). Because Shape does not know what kind of shape it is it does not know how to compute its area so it defines it as a pure virtual method. This means that there is no implementation; notice the = 0 after the method declaration, that means there is no method body defined for this method. The result here is that you can’t instantiate an instance of the Shape class as its incomplete and that any derived class will be required to provide one before it can be used. Look at the Rectangle and Square classes notice that they both declare the getArea() method and provide an implementation for it thus completing the Shape class and allowing it to be instantiated.

Next because the getter methods getWidth() and getHeight() are bound to be the same in most derived classes the Shape class does provide implementation for them but marks them as virtual methods so that derived classes can override them with their own unique implementation if needed; if they do not provide their own implementation the one defined by Shape will be used. See the Square class which is a derivative of the Shape class; a Square has the same length on all four sides so its width and height are the same, to insure that the width and height are always the same it provides its own unique implementation for the getHeight() method which returns the m_width variable instead of the m_height variable; this means for Square objects the getHeight() and getWidth() methods return the same value.

One last thing to point out before moving on; notice that I used the virtual keyword in the Square and Rectangle classes when re-implementing the virtual methods from the Shape class? This is optional, I could have defined these two classes as follows without compiler issue and with no change to functionality (they are still virtual and can be re-re-implemented in derivatives of Rectangle and Square):

class Rectangle : public Shape
{
public:
    Rectangle() {}
    virtual ~Rectangle() {}

    double getArea() 
    {
         return m_width * m_height;
    }
};


class Square: public Shape
{
public:
    Square() {}
    virtual ~Square() {}

    double getArea() 
    {
         return m_width * m_height;
    }
    int getHeight() 
    {
        return m_width;
    }
};

So where’s override?

OK so where override comes in is when we start talking about making the code self-documenting and easy to understand. Lets take a look at another example:

//In this example to keep things clean the implementation is not inline like above but in a CPP file (not shown). 
//Here we really don't need to worry about the implementation to understand the point I'm trying to make.
class MyChildClass: public MyParentClass
{
public:
    MyChildClass() {}
    virtual ~MyChildClass() {}

    virtual double getFOO();
    virtual int getBAR();
    bool isFubar();
};

Notice that class MyChildClass is a derivative of MyParentClass so that means some of the methods seen in MyChildClass could be re-implementations of methods defined in the parent class.

Pop quiz hot shot; which of the above three methods are re-implementations of methods from the parent class and which are net new methods added by MyChildClass?

<Insert fun quiz music here>

Give up? The correct answer is…. either (a) all of them, (b) none of them, (c) some of them, or (d) all of the above.

Say Whhaatttt?!

Once a method is marked virtual its always virtual, so if MyParentClass defines the isFubar() method as virtual bool isFubar() = 0; that means that no matter how the child (or grandchild) classes declare the isFubar() method it will always be virtual. So even though MyChildClass does not use the virtual keyword in its declaration of isFubar() if we created another class called MyGrandChildClass and had it derive off of MyChildClass I could still re-implement the isFubar() method within the MyGrandChildClass as it would be re-implementing the virtual method defined in MyParentClass superseding MyChildClass.

So assuming getFOO() and getBAR() are also virtual methods defined in MyParentClass why did you use the virtual keyword in MyChildClass?

A nicety is why. So your right as the methods are already virtual (assuming MyParentClass defined them as such) using the virtual keyword in MyChildClass is redundant; however, if I didn’t use said keyword we would have no way of knowing if they were local member methods or re-implementation of virtual methods from the parent class. Also if I was creating MyGrandChildClass I wouldn’t know off hand if I could re-implement them as I couldn’t just look at MyChildClass to figure out if they were virtual. I would have to spend time traversing the inherency tree to find the source of the method (i.e. MyParentClass) to figure out if they were virtual. So using the virtual keyword here even though redundant is a nicety to allow the code to be self-documenting and us as code authors not to have to flip through pages and pages of code to figure out how our classes work.

So if we can use the virtual keyword to document the codes intent what’s with the override keyword?

Well the virtual keyword as a code description tool isn’t perfect as its primary use is to mark a method as virtual not to document that a method is a re-implementation of a virtual method. In the above it was redundant as the method was already virtual but what if it wan’t? What if getFOO() was not defined in MyParentClass what would the line in MyChildClass be doing then? It would be defining a net-new method in MyChildClass which does not exist in MyParentClass and marking it as virtual. Perfectly fine however as a documentation tool problematic as getFOO() which is a net-new virtual method looks exactly the same as getBAR() which is a re-implementation from MyParentClass.

Secondly what if in the course of adding new features to our code we need to add a new input parameter to getBAR() but we only end up doing it in the MyChildClass not realizing that its a re-implementation of a MyParentClass method.

class MyChildClass: public MyParentClass
{
public:
    MyChildClass() {}
    virtual ~MyChildClass() {}

    virtual double getFOO();
    virtual int getBAR( bool hello );
    bool isFubar();
};

What happens now is that getBAR(bool) becomes a net-new virtual method and the original getBAR() method, no input parameter, is demoted to the base implementation provided by MyParentClass which isn’t probably what you wanted to happen. Worst yet what if getBAR() was a pure virtual method? Well now you have an incomplete class, the getBAR() implementation is missing, which will result in an error which simply states that you can’t create an instance of an abstract class with no hint that its due to your getBAR() change. If your class is unfortunately humongous this will take quite a while to figure out if you made a bunch of code changes.

C:\Users\bvanderlaan\Documents\GitHub\ImaginativeThinking_tutorials\Qt\Override_Sample1\main.cpp:12: error: cannot declare variable 'myClass' to be of abstract type 'MyChildClass'
     MyChildClass myClass;
                  ^

If you didn’t know getBAR() was a virtual method from the parent class you’d look at the above error with a screwed up face and say “what do you mean MyChildClass is abstract? I have all the implementation in MyChildClass.cpp you stupid compiler!”

Enter the override keyword

So as we said above if isFubar() is a re-implementation from a virtual method defined in MyParentClass we can’t tell unless we look it up in MyParentClass since in MyChildClass it looks the same as a locally defined method so we as a convention tend to annotate these types of methods with the virtual keyword like we did above with getFOO(). However as we just described that is still ambiguous as its hard to tell if getFOO() is a re-implementation from MyParentClass or a net-new virtual method without looking it up in MyParentClass. This also can cause confusing can’t declare abstract type errors. Therefore what we really need is a way to annotate re-implementations without causing them to be created as net-new virtual methods and can tell us when we’ve broken things by changing the re-implementation signature without updating the virtual declaration in the parent class.

That is exactly what the override keyword is meant to do.

Lets take a look at the above example again but instead of annotating the virtual methods re-implementations with the virtual keyword we use the override keyword.

class MyChildClass: public MyParentClass
{
public:
    MyChildClass() {}
    virtual ~MyChildClass() {}

    virtual double getFOO();
    int getBAR( bool hello ) override;
    bool isFubar();
};

Now lets ask the question again: Which of the above three methods are re-implementations of methods from the parent class and which are net new methods added by MyChildClass?

<Insert fun quiz music here>

Answer: isFubar() is a non-virtual local method, getBAR(bool) is a re-implementation of a virtual method defined in MyParentClass and getFOO() is a net-new virtual method defined in MyChildClass.

See how clear this code is now, it tells you exactly what is going on without the need to switch code files.

Secondly lets assume that the virtual method in MyParentClass is getBAR() with no Boolean input parameter which means we can’t use MyChildClass as its incomplete (we didn’t provide an implementation for the no parameter version of getBAR()). This time when we compile we get a must better to understand error:

C:\Users\bvanderlaan\Documents\GitHub\ImaginativeThinking_tutorials\Qt\Override_Sample1\MyChildClass.h:15: error: 'int MyChildClass::getBAR(bool)' marked override, but does not override
     int getBAR( bool hello ) override;
         ^

C:\Users\bvanderlaan\Documents\GitHub\ImaginativeThinking_tutorials\Qt\Override_Sample1\main.cpp:12: error: cannot declare variable 'myClass' to be of abstract type 'MyChildClass'
     MyChildClass myClass;
                  ^

We get both the original confusing can’t declare abstract class error but also a new error that tells us that we have a method which is suppose to be re-implementing/overriding a virtual method but no virtual method exists for it to override. This turns a confusing head scratchier into a simple ah, silly me moment.

The other nice thing about the override keyword is that it can also protect you from cases where a virtual method is removed from a base class. You might have intended to remove the method from the parent and all its derivatives but without the override keyword you have to hunt for them; with the override keyword you can simply lean on the compiler to catch all the instances of your re-implemented method then choose to keep them (by removing the override keyword) or remove them.

But wait my compiler does not support C++11

If your current compiler does not yet support C++11 but you want to start getting into the habit of using the override keyword or you have a shared library that is used on a new project which uses a newer compiler with C++11 support and an older project which is stuck on an older compiler without C++11 support then what are you to do?

Macros!

You can always define your own Macro and use a compiler definition to specify if the override keyword should be used or not. The older project is SOL but at least the newer project can benefit from the override keyword without breaking the older project or causing you to branch your code. If your using Qt 5.0 or greater then one already exists for you: Q_DECL_OVERRIDE.

class MyChildClass: public MyParentClass
{
public:
    MyChildClass() {}
    virtual ~MyChildClass() {}

    virtual double getFOO();
    int getBAR( bool hello ) Q_DECL_OVERRIDE;
    bool isFubar();
};

The Q_DECL_OVERRIDE will be substituted to the override keyword if the compilers supports it or to nothing if not.

So that is what the heck the override keyword is; a C++11 addition which lets you annotate virtual method re-implementations in a way that does not introduce new virtual methods and can produce meaningful error messages.

You can find the source code used in the above at my GitHub repository ImaginativeThinking_tutorials.

If you have any questions or comments please leave them below and I’ll write back as time permits.

Until next time think imaginatively and design creatively

Brad

My interest in computer programming started back in high school and Software Development has remained a hobby of mine ever since. I graduated as a Computer Engineering Technologist and have been working as a Software Developer for many years. I believe that software is crafted; understanding that how it is done is as important as getting it done. I enjoy the aesthetics in crafting elegant solutions to complex problems and revel in the knowledge that my code is maintainable and thus, will have longevity. I hold the designation Certified Technician (C.Tech.) with the Ontario Association of Computer Engineering Technicians and Technologists (OACETT), have been certified as a Professional Scrum Master level 1 (PSM I) and as a Professional Scrum Developer level 1 (PSD I) by Scrum.org as well as designated as an Officially Certified Qt Developer by the Qt Company. For more on my story check out the about page here

Feel free to write a reply or comment.