Héritage virtuel
#include <iostream>
using namespace std;
class Creature
{
public:
Creature():age(3)
{ cout << "Exécution du constructeur de Créaturen"; }
~Creature()
{ cout << "Exécution du destructeur de Créaturen"; }
void Dormir(){}
int LireAge() const { return age; }
private:
int age;
};
class Enfant : virtual public Creature
{
public:
Enfant()
{ cout << "Exécution du constructeur de Enfantn"; }
~Enfant()
{ cout << "Exécution du destructeur de Enfantn"; }
void Marcher(){}
void Rire(){}
protected:
private:
};
class Oiseau : virtual public Creature
{
public:
Oiseau()
{ cout << "Exécution du constructeur de Oiseaun"; }
~Oiseau()
{ cout << "Exécution du destructeur de Oiseaun"; }
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() << " ansn";
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()<<" ansn";
cout << "Il pèse " << amour.LirePoids() << " kgn";
cout << "Et il a " << amour.LireDents() << " dentsn";
}
Vous obtenez :
Notre chérubin a 4 ans
Il pèse 20 kg
Et il a 10 dents |