Finally, overriding is valid only
for virtual methods, and the idea is to redefine, in a subclass,
a virtual method inherited from a superclass
allowing what is known as
dynaming binding, and polymorphism.
The method of the actual instance will be invoked if it is called
via a pointer or a reference and, similarly to shadowing,
if we redefine only one virtual method,
it will override all the others,
even if they don't have the same parameters.
Only one will be defined, but it will simply hide the others.
The rules of shadowing also apply to overridden functions.
Let's review this in detail in an example:
Imagine that we have three classes A, B and C
such that B and C both inherit from A.
These three classes will have a method <i>m1</i> which
we will overload, override and shadow.
To make the example a bit more concrete,
in the main function, we have an instance b of class B
and an instance c of class C.
We will go over the different ways of calling these m1 methods.
In class A, we have a first m1 method which takes an integer.
Each of these methods will simply display
a message indicating which method was called.
Moreover, in A, we also have an m1 method which has a different list of parameters
than the first method.
Here, it takes a string instead of an integer.
These two m1 methods have the same scope, the scope of class A.
They have different lists of parameters, but the same name.
This is therefore a simple case of overloading.
In class B, we have an override of one of the two methods.
We override the method which takes a string
as argument.
This m1 method overridden here in the B subclass of A
thus hides A's m1 method in B.
Since it is the only method of the two which was overridden in B,
based on rules of scope and shadowing,
this method also masks the other method since in class B,
we will only have one accessible m1 method.
Class B will effectively have three m1 methods.
Its own m1 method and the two m1 methods inherited from the superclass, A.
But because of scope resolution rules,
when we are in B, we resolve to the closest scope,
and the only one directly accessible is the one that was
defined in B, which thus hides both of A's methods.
Let's look at this in the main.
Here, we have our instance b. We cannot make a call like this.
This is why we commented the m1 method that takes an integer
since the m1 method taking an integer, inherited from A,
is hidden by the method in B which takes a string.
We can indeed call the m1 method
which takes a string. This poses no problem at all.
But we cannot call the method from m1 taking an integer.
We get a message saying that this function cannot be called.
However, it does exist; if we want to call it, we will have to use
the scope resolution operator
saying "the method m1 of scope of class A which belongs
to the instance b of subclass B".
which does indeed inherit this method from class A since B is an A.
This method can thus be called here
but it will need to be "unhidden" using the scope resolution operator.