The problem is how to display a generic character.
We don't know how to display a generic character.
We certainly know how to display a warrior, a magician or a thief,
so each of the specific subclasses knows how to be displayed;
however, at the general level of a character,
we don't necessarily know how to display it.
But we know that we need to do so, here at the very general level of the game,
we know we will have to display the characters.
So, how do we do so?
Of course, if we do nothing in the "Personnage" class,
if we do not define any "afficher" method in "Personnage",
then the "afficher" method in Jeu would not compile
since here, we call the "afficher" method of a character
and the compiler would not know what to do,
it would give us an error.
So we should be able to write this at the global level of the game,
we must introduce an "afficher" method in the "Personnage" class.
Moreover, we would like to impose to each of the subclasses,
warriors, magicians, to be displayed with their own "afficher" method,
to have a specific method, and that it is this specific method
which should be called in the general call here at the level of the game.
Essentially, we want to force the presence of a specific
method at the class level, and we want this method to be polymorphic.
So this method has to be "virtual"
and exist at the character level.
But how do we do this if we don't know
-- suppose that we don't know how to display a generic character.
What's more, how do we force subclasses to override this
"afficher" method?
First solution for the first problem:
how to define the display for a generic character.
We could have some arbitrarily-defined method,
for example, suppose that here, we arbitrarily define
that the display for a generic character
is no display at all.
This solution is a very bad idea,
because, first, it is a bad model of reality
as characters do not appear as nothing,
so it doesn't correspond to anything, the display is incorrect.
And what's more, the display would be incorrect
if a subclass forgot to override this method;
in that case, we would have characters that would not be displayed,
phantom characters, which could be a problem for the game.
Moreover, this solution does not address the second problem,
it does not force the subclasses to define their own "afficher" method.
The only good solution is to indicate that the "afficher" method
must exist and must be defined in each of the subclasses.
This is known as a "pure virtual method".
I hope this second example has allowed you to understand
the need for these pure virtual methods
in defining general, abstract superclasses.
Now, let's see how all of this is actually written in C++.
A pure virtual method, also known as an "abstract method",
is used to force subclasses
to override the inherited virtual method.
To define a pure virtual method, an abstract method,
we simply add "= 0" at the end of its prototype.
For example, if in the "Personnage" class
we had written the virtual method "afficher"
-- the "afficher" method does not modify a character --
and at the end of its prototype,
instead of just having a semicolon, we also added "= 0".
Then this would define a pure virtual method, an abstract method.
Generally, a pure virtual method is only partly specified,
meaning that there is usually no definition
but only a prototype in the class in which it was introduced.
This is not a strict requirement, but it is often the case.
Here for example, we would not define the "afficher" method
for a generic character;
we expect that each subclass will define its own "afficher" method
specific to warriors, magicians, thieves,...
If I go back to the other example, the one with the closed figures,
we would have a "surface" method, which would be a pure virtual method,
so here we would add "= 0" to the end of its prototype,
that we could still use,
We are allowed to call pure virtual methods.
we can for instace define a "volume" method
which we have not defined as virtual
as there is no reason for a subclass to override this volume method,
which takes a height and calculates the volume occupied
as the product of the height and the result of the call to the surface method,
where the surface method will be the one belonging to the instance on which it is called.
Because as we will see,
a class containing a pure virtual method,
such as FigureFermee, cannot be instantiated
and so we will never call the surface method
directly on a FigureFermee object.
However we can imagine subclasses such as rectangles or circles
who know how to calculate their surface area.
So we will call the circle's method if it is a circle,
or the rectangle's method if it is a rectangle --
that is the polymorphic aspect,
enabled by this "virtual" keyword.
Here, we call the surface method through a pointer,
indeed, remember that this is exactly the same as writing
"this -> surface", as we might easily forget,
and so here, polymorphism is used
since we make the call through a pointer,
even if it is not explicitly written, and the method is virtual.
Another pure virtual method that we could define
at the level of the FigureFermee class is the concept of the perimeter.
The method would return the perimeter of a closed figure,
and we don't necessarily know how to define this generally either
at the level of the very generic, abstract class describing closed figures.
But we could imagine being able to define this properly in subclasses.
We will return to this example shortly.
A class containing a pure virtual method such as this one
is known as an abstract class.
It is indeed an abstract class because
if a class contains a pure virtual method,
then it cannot be instantiated.
We cannot create instances of this class.
For example, we cannot declare a variable of type "Personne",
and of course any subclass that inherits from an abstract superclass
remains abstract as long as it doesn't provide definitions
for the pure virtual functions they inherited.
In other words, as long as they haven't removed the "= 0"
from the prototypes of their override of the pure virtual method
inherited from the superclass.
Let's take a look at this through an example,
our example of a game with characters,
where a warrior is a character,
and has inherited a pure virtual method,