"Héritage", c'est un drôle de mot pour de la programmation hein

Alors c'est quoi ? C'est une technique qui permet de créer une classe à partir d'une autre classe. Elle lui sert de modèle, de base de départ. Cela permet d'éviter à avoir à réécrire un même code source plusieurs fois.
Comment reconnaître un héritage ?
C'est LA question à se poser. Certains ont tellement été traumatisés par l'héritage qu'ils en voient partout, d'autres au contraire (surtout les débutants) se demandent à chaque fois s'il y a un héritage à faire ou pas. Pourtant, ce n'est pas "mystique", il est très facile de savoir s'il y a une relation d'héritage entre 2 classes.
Comment ? En suivant cette règle très simple :
Il y a héritage quand on peut dire :
"A est un B"
Pas de panique c'est pas des maths

Prenez un exemple très simple. On peut dire "Un guerrier est un personnage", ou encore "Un magicien est un personnage". Donc on peut faire un héritage : "La classe Guerrier hérite de Personnage", "La classe Magicien hérite de Personnage".
Pour vous imprégner, voici quelques autres bons exemples où un héritage peut être fait :
- Une voiture est un véhicule (Voiture hérite de Vehicule)
- Un bus est un véhicule (Bus hérite de véhicule)
- Un moineau est un oiseau (Moineau hérite d'Oiseau)
- Un corbeau est un oiseau (Corbeau hérite d'Oiseau)
- Un chirurgien est un docteur (Chirurgien hérite de Docteur)
- Un diplodocus est un dinosaure (Diplodocus hérite de Dinosaure)
- etc.
En revanche, vous ne pouvez pas dire "Un dinosaure est un diplodocus", ou encore "Un bus est un oiseau". Donc on ne peut pas faire d'héritage dans ces cas-là, du moins ça n'aurait aucun sens
J'insiste, mais il est très important de respecter cette règle. Vous risquez de vous retrouver avec des gros problèmes de logique dans vos codes si vous ne le faites pas.
Nous allons voir comment réaliser un héritage en C++, mais d'abord il faut que je pose l'exemple sur lequel on va travailler
Notre exemple : la classe Personnage
Petit rappel : cette classe représente un personnage d'un jeu vidéo de type RPG (jeu de rôle). Il n'est pas nécessaire de savoir jouer ou d'avoir joué à un RPG pour suivre mon exemple. J'ai juste choisi celui-là car il est plus ludique que la plupart des exemples barbants que les profs d'informatique aiment utiliser (Voiture, Bibliothèque, Université, PompeAEssence...).
On va un peu simplifier notre classe Personnage. Voici ce sur quoi je vous propose de partir :
Code : C++ - Personnage.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | #ifndef DEF_PERSONNAGE
#define DEF_PERSONNAGE
#include <iostream>
#include <string>
class Personnage
{
public:
Personnage();
void recevoirDegats(int degats);
void coupDePoing(Personnage &cible) const;
private:
int m_vie;
std::string m_nom;
};
#endif
|
Notre Personnage a un nom et une quantité de vie.
On n'a mis qu'un seul constructeur, le constructeur par défaut. Il permet d'initialiser le Personnage avec un nom et lui donnera 100 points de vie.
Le Personnage peut recevoir des dégâts, via la méthode
recevoirDegats() et en distribuer, via la méthode
coupDePoing().
A titre informatif, voici l'implémentation des méthodes dans Personnage.cpp :
Code : C++ - Personnage.cpp 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | #include "Personnage.h"
using namespace std;
Personnage::Personnage() : m_vie(100), m_nom("Jack")
{
}
void Personnage::recevoirDegats(int degats)
{
m_vie -= degats;
}
void Personnage::coupDePoing(Personnage &cible) const
{
cible.recevoirDegats(10);
}
|
Rien d'extraordinaire pour le moment.
La classe Guerrier hérite de la classe Personnage
Intéressons-nous maintenant à l'héritage. L'idée, c'est de
créer une nouvelle classe qui est une sous-classe de Personnage. On dit que cette classe va
hériter de Personnage.
Pour cet exemple, je vais créer une classe Guerrier qui hérite de Personnage. La définition de la classe, dans Guerrier.h, ressemble à ceci :
Code : C++ - Guerrier.h 1
2
3
4
5
6
7
8
9
10
11
12
13 | #ifndef DEF_GUERRIER
#define DEF_GUERRIER
#include <iostream>
#include <string>
#include "Personnage.h" // Ne pas oublier d'inclure Personnage.h pour pouvoir en hériter !
class Guerrier : public Personnage // Signifie : créer une classe Guerrier qui hérite de la classe Personnage
{
};
#endif
|
Grâce à ce qu'on vient de faire, la classe Guerrier contiendra de base tous les attributs et toutes les méthodes de la classe Personnage.
Dans un tel cas, la classe Personnage est appelée la classe "Mère", et la classe Guerrier la classe "Fille".
Mais quel intérêt de créer une nouvelle classe si c'est pour qu'elle contienne les mêmes attributs et les mêmes méthodes ?
Attendez, justement ! Le truc, c'est qu'
on peut rajouter des attributs et des méthodes spéciales dans la classe Guerrier. Par exemple, on pourrait rajouter une méthode qui ne concerne que les guerriers, du genre frapperCommeUnSourdAvecUnMarteau (bon ok c'est un nom de méthode un peu long j'avoue

).
Code : C++ - Guerrier.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #ifndef DEF_GUERRIER
#define DEF_GUERRIER
#include <iostream>
#include <string>
#include "Personnage.h"
class Guerrier : public Personnage
{
public:
void frapperCommeUnSourdAvecUnMarteau() const; // Méthode qui ne concerne que les guerriers
};
#endif
|
Schématiquement, on représente la situation comme ça :
Le schéma se lit de bas en haut, c'est-à-dire "Guerrier hérite de Personnage".
Guerrier est la classe fille, Personnage est la classe mère. On dit que Guerrier est une "spécialisation" de la classe Personnage. Elle possède toutes les caractéristiques d'un Personnage (de la vie, un nom, elle peut recevoir des dégâts), mais possède en plus des caractéristiques propres au Guerrier comme
frapperCommeUnSourdAvecUnMarteau().
Retenez bien que lorsqu'on fait un héritage, on hérite des méthodes et des attributs.
Je n'ai pas représenté les attributs sur le schéma ci-dessus pour ne pas surcharger, mais la vie et le nom du Personnage sont bel et bien hérités, ce qui fait qu'un Guerrier possède aussi de la vie et un nom !
Vous commencez à comprendre le principe ? En C++, quand on a deux classes qui sont liées par la relation EST-UN, on utilise l'héritage pour mettre en évidence ce lien. Un Guerrier EST-UN Personnage amélioré qui possède une méthode supplémentaire.
Ce concept a l'air de rien comme ça, mais croyez-moi ça fait la différence ! Vous n'allez pas tarder à voir tout ce que ça a de puissant lorsque vous pratiquerez plus loin dans le cours.
La classe Magicien hérite aussi de Personnage
Tant qu'il n'y a qu'un seul héritage, l'intérêt semble encore limité. Mais multiplions un peu les héritages et les spécialisations et nous allons vite voir tout l'intérêt de la chose.
Par exemple, si on créait une classe Magicien qui va elle aussi hériter de Personnage ? Après tout, un Magicien est un Personnage, donc il peut récupérer les mêmes propriétés de base : de la vie, un nom, donner un coup de poing, etc.
La différence, c'est que le Magicien peut aussi envoyer des sorts magiques, par exemple bouleDeFeu et bouleDeGlace. Pour utiliser sa magie, il a une réserve de magie qu'on appelle "Mana" (ça va faire un attribut à rajouter). Quand la Mana tombe à zéro, il ne peut plus lancer de sort.
Code : C++ - Magicien.h 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | #ifndef DEF_MAGICIEN
#define DEF_MAGICIEN
#include <iostream>
#include <string>
#include "Personnage.h"
class Magicien : public Personnage
{
public:
void bouleDeFeu() const;
void bouleDeGlace() const;
private:
int m_mana;
};
#endif
|
Je ne vous donne pas l'implémentation des méthodes (le .cpp) ici, je veux juste que vous compreniez et reteniez le principe :
Notez que sur le schéma je n'ai représenté que les méthodes des classes, mais les attributs (vie, nom...) sont eux aussi hérités !
Et le plus beau, c'est qu'on peut faire une classe qui hérite d'une classe qui hérite d'une autre classe !

Imaginons qu'il y ait 2 types de magiciens : les magiciens blancs, qui sont des gentils qui envoient des sorts de guérison tout ça tout ça, et les magiciens noirs qui sont des méchants qui utilisent leurs sorts pour tuer des gens (super exemple, j'en suis fier).
Avada Kedavra !
Et ça pourrait continuer longtemps comme ça. Vous verrez dans la prochaine partie sur la bibliothèque C++ Qt qu'il y a souvent 5 ou 6 héritages qui sont faits à la suite. C'est vous dire si c'est utilisé !