Héritage virtuel
Héritage virtuel
Code 7.9 : héritage virtuel
#include <iostream> using namespace std; class Creature { public: Creature():age(3) { cout << "Exécution du constructeur de Créature\n"; } ~Creature() { cout << "Exécution du destructeur de Créature\n"; } void Dormir(){} int LireAge() const { return age; } private: int age; }; class Enfant : virtual public Creature { public: Enfant() { cout << "Exécution du constructeur de Enfant\n"; } ~Enfant() { cout << "Exécution du destructeur de Enfant\n"; } void Marcher(){} void Rire(){} protected: private: }; class Oiseau : virtual public Creature { public: Oiseau() { cout << "Exécution du constructeur de Oiseau\n"; } ~Oiseau() { cout << "Exécution du destructeur de Oiseau\n"; } void Chanter(){} void Voler(){} }; class Cherubin : public Enfant, public Oiseau {}; int main() { cout << "On crée un objet Cherubin" << endl; Cherubin amour; cout << "Notre chérubin a " << amour.LireAge() << " ans\n"; return 0; }
Voici le résultat de l’exécution :
On crée un objet Cherubin Exécution du constructeur de Créature Exécution du constructeur de Enfant Exécution du constructeur de Oiseau Notre chérubin a 3 ans Exécution du destructeur de Oiseau Exécution du destructeur de Enfant Exécution du destructeur de Créature
Avec l’héritage virtuel, Cherubin n’hérite que d’une copie des membres de Creature et l’ambiguïté est résolue.
En effet, un constructeur initialise généralement ses variables et la classe de base dont il dépend. Les classes dont l’héritage est virtuel (comme Creature dans cet exemple) sont initialisées par la classe de dérivation « la plus élevée » (Cherubin). Creature est donc initialisée par Cherubin et non par Enfant ou Oiseau.
Si un membre de Creature a besoin d’être initialisé, alors Enfant et Oiseau doivent l’initialiser (procédure habituelle) mais aussi Cherubin. Cela permet de résoudre l’ambiguïté d’une initialisation différente dans Enfant et Oiseau.
Le code 7.10 illustre l’initialisation de la donnée membre age de la classe de base Creature dans chacune des classes dérivées.
Code 7.10 : héritage virtuel avec initialisation de membres de la classe de base
#include <iostream> using namespace std; class Creature //classe de base { public: Creature(int un_age):age(un_age){} void Dormir(){} int LireAge() const { return age; } private: int age; }; //Enfant hérite de la classe de base virtuelle Creature class Enfant : virtual public Creature { public: //le constructeur initialise un_age et nombre_dents Enfant(int un_age, int combien_de_dents): Creature(un_age), nombre_dents(combien_de_dents){} void Marcher(){} void Rire(){} int LireDents() const { return nombre_dents; } private: int nombre_dents; }; //Oiseau hérite de la classe de base virtuelle Creature class Oiseau : virtual public Creature { public: //le constructeur initialise un_age et poids Oiseau(int un_age, int le_poids): Creature(un_age), poids(le_poids){} void Chanter(){} void Voler(){} int LirePoids() const { return poids; } private: int poids; }; //Cherubin hérite de Creature, Enfant et Oiseau : class Cherubin : public Enfant, public Oiseau { public: Cherubin(int un_age, int le_poids, int combien_de_dents): // on initialise la classe de base Enfant Enfant(un_age, combien_de_dents), // on initialise la classe de base Oiseau Oiseau(un_age, le_poids), // on initialise la classe de base virtuelle Creature! Creature(un_age){} }; int main() { int son_age = 4; int son_poids = 20; int ses_dents = 10; /*on crée un objet Cherubin en initialisant les trois variables */ Cherubin amour(son_age, son_poids, ses_dents); cout<<"Notre chérubin a "<<amour.LireAge()<<" ans\n"; cout << "Il pèse " << amour.LirePoids() << " kg\n"; cout << "Et il a " << amour.LireDents() << " dents\n"; }
Vous obtenez :
Notre chérubin a 4 ans Il pèse 20 kg Et il a 10 dents
Le texte original de cette fiche pratique est extrait de
«Tout sur le C++» (Christine EBERHARDT, Collection
CommentCaMarche.net, Dunod, 2009)