In this video, we'll learn about the c++11 override specifier.
We know that we can override base class virtual functions in our derived classes.
We also know that we must provide the exact function signature
in the derived class, including the return type.
But what if we don't?
What if we inadvertently make a small change to the function signature by mistake?
If this happens, then the function we intended to override doesn't get overwritten at all.
Instead it gets redefined,
and we know that redefined functions are statically bound, not dynamically bound.
This type of error is really hard to find sometimes
since the function signatures may look very, very similar,
and it may not be easy to spot the difference.
C++11 addresses this issue
by providing the override specifier.
You can add this specifier to the method you're writing in your derived class,
and the c++ compiler will ensure that you're indeed overriding and not redefining.
This is a simple addition to the language but a very useful one.
Let's see what it looks like in code.
Here we have two simple classes in a class hierarchy.
The base class has a virtual function named "say hello".
It returns nothing, expects nothing and is a const function.
In the derived class, I wanted to override this function.
But when I wrote the function prototype, I forgot the const at the end of the prototype.
Since the function signatures are not exactly, the same
the c++ compiler considers this function redefinition and not overriding.
It will compile just fine since this is perfectly legal.
Let's see the difference between the methods.
Here it might be easier to see that the function signatures are indeed different.
So the say hello function of the derived class will be statically bound,
not dynamically bound, as we expected.
This will cause unexpected behavior when we use a base class pointer.
Here we have two pointers to a base class object, P1 and p2.
P1 is pointing to a base object, and p2 is pointing to a derived object.
When I call say hello via p1,
this will be bound dynamically, and it will call bases "say hello".
However, when I call say hello via pointer 2,
I expect it to display hello I'm a derived class object
because I expected dynamic binding,
but I messed up when i created the function by not matching the signature exactly.
So the function call is statically bound to base say hello.
We can easily prevent this error by using the c++11 override specifier.
Notice the say hello function of the derived class.
We can place the override specifier after the function prototype.
This tells the compiler that you intend to override this function,
and it should make sure that you do so.
In this case, the compiler will produce an error, and you can add that const to fix the problem.
Let's head over to the IDE and see this example in live code.
I'm in the IDE, and I'm on the section 16 workspace
in the UsingOverride project.
You can see here that I've got a simple base class.
And all it has inside is a virtual function right here
called say hello. And notice that this is a const function.
And all it says is hello I'm a base class object.
Now I've got a derived class here that's derived publicly from the base class.
And what I meant to do here was to override this say hello function right here.
But I messed up, and I forgot that const right there.
So it should have had a const there, but it doesn't. So now as far as the compiler is concerned,
this function, right here in my derived class,
is redefining the base class function, not overriding it.
So it's going to statically bind it rather than dynamically bind it.
Okay. So let's take a look at the main,
and we'll walk through this you can see exactly what's going to happen.
Okay, so here's p1 and p1 is a pointer to a base object.
And I'm instantiating a base object and pointing right to it.
So now when I call say hello via that p1 pointer,
obviously, this is going to do dynamic binding,
and it's going to bind it to my base class since that's what I'm pointing to so
this will call base say hello.
In this example, this is a little different than what we've seen.
Here I have p2 is a pointer to a derived object,
and I'm instantiating a derived object.
So in this case, what's going to happen is this is not a base class pointer,
this is just a regular old pointer to an object.
So in this case, it's going to be statically bound, and we're going to call derived say hello.
This is the problematic one right here, p3.
The problem here is since we did not override instead we redefined,
this will not be bound dynamically, it'll be bound statically.
So as far as the compiler is concerned,
I've got a base pointer right here, so it's going to bind it to base say hello.
But I really wanted it to bind to derive say hello.
All right. So let's run this, and then what we'll do is we'll fix this with the override keyword.
So let me run this.
And here's our output. And you can see our main. Let me scroll up just a little bit right here.
So you can see here p1 points to a base and it's looking at a base.
So hi, I'm a base class object.
In the case of p2,
we're statically binding because we're pointing to a derived object and that's exactly what we have.
So it's going to say hello, I'm a derived class object.
Here's the problematic one on line 30.
P3 is pointing to a base object, and it's currently
pointing to the derived, right.
Here's where the problem is because
I redefined that function so it's going to be statically bound rather than dynamically bound,
so it's going to call base say hello and you can see right there,
Hi, I'm a base class object. That's not what I wanted.
I wanted it to say "hello, I'm a derived class object"
because I wanted it to use dynamic polymorphism.
So how do we fix this? Well, the fix is easy, right. We just come up here and put const in there.
But we can also use the override keyword in c++11,
which is really handy. You really should do this every time that you're going to overwrite a function in a derived class,
simply put the override word in there.
Right there, you can put the override specifier right at the end of the function prototype.
So now when you compile, let me just build this real quick,
now you get an error. And the error says virtual void derive say hello marked as override,
but it does not override.
That gives you a really good clue as to you're not overriding anything here.
So you can come in here and say oh okay, I got it. There's my const.
You can put your const in there now. And then when you run,
you can see that now -- let me scroll up just a little bit,
now you can see that third statement it says "hello, I'm a derived class object". That's what we want.
So now we've got our polymorphic behavior.
So real handy, really easy to do, use it all the time,
and it'll save you a lot of grief with debugging.