Hello again! In this video, we are going to look at virtual functions in C++11.
So we now know that we can get dynamic binding if we have a virtual member function in the base and
we override that in the child, and we call this member function through a pointer to the base.
For this to work, the function in the child has to have the same signature as the function in the
parent.
So we saw that with the Circle and the Triangle. They had the same signature as the parent's virtual
draw() function.
It's the same function has a different signature, then that is not an override.
It is actually an overload.
So it's actually regarded as a different function.
So dynamic binding does not work in that case.
And also, if we try to call the parent's version of the member function through the child, then we get a
compile error, because the member function has been hidden and we need to put in a "using" directive
to make the parent's member function available again. Unfortunately, it is quite easy to get an override wrong.
If you are adding the member function to the child and you make a mistake when you are defining the function.
Or perhaps someone changes the parent's signature and they forget to change the child. Most of the time
you will not get a compiler error. If you try to call a hidden member function, then you will get compiler
error.
But apart from that, there is no indication. Until you run the program and it does not work properly,
and you are not sure why.
In C++11, we can now get the compiler to check this for us.
We can say that a member function is meant to be an override, and the compiler will check whether
this is actually an override
of a virtual function in the parent's class. And if it is not, then we get a compiler error.
So let's try this out.
So we have our Sheep class again with the virtual draw() member function.
Then we have the child with the override of the parent's draw() with no arguments, returning void.
Although the return value is not part of the signature, of course.
They are both declared const.
So these both have the same signature. If we add another function, which is meant to be an override.
Which takes an argument, because it is useful to have an argument.
Let's see what happens.
And we get a compiler error. Circle::draw() did not override any base class methods.
So that is obviously this one.
If we remove the override key word.
Then it compiles.
And if we comment out, then we get another error. So that is the hiding again.
So, Circle::draw() function does not take zero arguments.
And we could put in a using declaration to...
...fix that.
OK.
So this is actually a very useful feature.
I recommend using the override keyword, every time that you are overriding an inherited virtual
member function.
The other key word in C++11, which is related to virtual member functions, is the "final" key word. And you
may have seen similar concepts in other languages.
If we say that a class is final, that means we cannot inherit from this class.
We cannot create any children of this class.
So a final class represents the end of the class hierarchy.
If we say that a member function is final,
this means that children of the class are not allowed to override it.
This is mostly useful to people who are writing libraries.
If you have a library which provides an inheritance hierarchy to users of the library, or maybe you just want
to use the hierarchy internally, you can use the final key word to prevents uses of your library from extending
your class hierarchy, and that will help you keep things under control.
So we're going to make our Circle class final.
So this means if we try to divide a class from Circle, say, a DeluxeCircle, then that should not
work, because final means you cannot create any children.
And there we are. "Cannot inherit from Circle as it has been declared as final".
If we remove that. OK, there is no main function, but the inheritance bit works.
So let's change this so that the Circle class is not final anymore.
If instead we make the draw() member function final.
So we are allowed to inherit from Circle, but we are not allowed to override the draw() member function.
And there we are. Function declared as final cannot be overridden by DeluxeCircle::draw.
So the final member function in Circle means that children of Circle are not allowed to override the draw()
member function.
Okay, so that is it for this video.
I will see you next time, but until then, keep coding!