Hello again! In this video, we are going to start looking at virtual functions.
This video is mainly going to be a recap of the previous video, about static and dynamic types.
But we are going to go a little bit further.
I think it is worth spending time making sure that we all understand the concepts, because it can be a
bit hard to grasp at first, if you have not seen it before.
And also every - I think, every - interview that I have had on C++ involved a question on virtual functions.
So it certainly is worth making sure that you understand it.
Normally, when we call a member function, the compiler will decide which function gets called.
So in code like this, if the draw() member function is a normal member function, then the compiler will see that
"rShape" is a reference to a Shape object. And it is going to call the Shape member function, even
though the actual object being referred to is a Circle. So that uses the static type.
And this process is known as "static binding".
There are some cases where the dynamic type is used.
So in that case, the compiler will not make the decision.
It just puts some extra code into the binary.
And then, when the program is run, that code is used to decide which function gets called. And that
will use the dynamic type of the object, and that is known as "dynamic binding".
Dynamic binding can only happen if two conditions are true.
We must be calling a member function through a pointer or a reference to a base class. And usually
the pointer will actually be pointing to a child object, or the reference will be a reference to
a child object.
And also, the member function has to be declared "virtual" in the base class.
To make a function virtual, we put the "virtual" key word before the declaration in the base class, like that.
And then this "virtual" member function will be inherited by all the subclasses of the base.
So that is the children, grandchildren and so on.
If a child class re-implements this virtual function, we say that the child overrides the base
class version.
So we have code like this. We have a Shape
as the base class, with a virtual draw() member function.
We have a Circle, which is the child class, and overrides the draw() member function.
And then, when we call the draw() on a reference to a Shape, which is bound to a Circle object, that
will use dynamic binding, and the Circle version of draw() will be called.
We were talking about having a function which can take any object from a class hierarchy.
If we have to use the static type, then we need to write a separate overload for each possible class.
And if we add another class to the hierarchy, then we need to write another overload.
With virtual functions, this becomes much easier.
We can pass a reference or a pointer to the base class. And then, in the function, if we call the virtual
member function, that will use dynamic binding, and it will call the right version for the actual object
that was passed.
So for example, if we pass a Circle by reference - or we could also pass by address - then this draw() member
function will use dynamic binding, and it will call the Circle version of draw().
So let's try this out.
We have our Shape class, with the virtual draw() member function.
We have the child class, which overrides the draw() member function. And then we have a function which
takes the Shape object by reference, and that is going to use dynamic binding.
So whenever it calls the draw() member function, which was declared virtual in the Shape class, we can
give it any subclass of Shape and it will call the member function of that subclass.
So there you are.
We give it a Circle and it calls the Circle member function. The real advantage of this is if we add another class
to the hierarchy.
So let's do that.
So we have the same code as before, but now we have a Triangle class, which also inherits
from Shape, and overrides the draw() member function.
Then we call the draw_shape() function with the Triangle being passed by reference.
Again, this will use dynamic binding. And this call to the draw() member function will call the Triangle
version of the virtual member function.
So there you are.
We can add a new class and our Shape function still works, even though we did not know about the
Triangle class when we vote this draw_shape().
Okay, so that is it for this video.
I will see you next time.
Until then, keep coding!