Cours Heritage
Cours Heritage
Cours Heritage
Thierry Vaira
[email protected] « v0.1
Sommaire
1 Classes et objets
2 L’héritage
3 Polymorphisme
4 Classe abstraite
5 Transtypage
Classes et objets
Classifier
État et comportement
Les droits d’accès aux membres d’une classe concernent aussi bien les
méthodes que les attributs.
En C++, on dispose des droits d’accès suivants :
- Accès public : on peut utiliser le membre de n’importe où dans le
programme.
- Accès private : seule une fonction membre de la même classe A
peut utiliser ce membre ; il est invisible de l’extérieur de
A.
- Accès protected : ce membre peut être utilisé par une fonction de
cette même classe A, et pas ailleurs dans le programme
(ressemble donc à private), mais
il peut en plus être utilisé par une classe B qui hérite de A.
Définition
Types d’héritage
unePersonne = unEtudiant; // Ok !
Conclusion : Traiter un type dérivé comme s’il était son type de base est
appelé transtypage ascendant ou surtypage (upcasting).
Principes (1/2)
L’héritage permet :
Principes (2/2)
// Classe de base
class Personne {
private: string nom;
public:
string getNom() const;
void afficher() const { cout << nom << endl; }
};
// Classe dérivée
class Etudiant : public Personne {
private: string ine;
public:
string getINE() const; // ajout de nouvelles fonctionnalités
void afficher() const // modification d’un comportement existant
{
Personne::afficher(); // réutilisation du code déjà écrit
cout << ine << endl;
}
};
Notion de redéfinition
Comme une instance de Etudiant (classe dérivée) est avant tout une
instance de Personne (classe de base), dans le constructeur de
Etudiant, on explicite la façon de créer l’instance Personne dans la
liste d’initialisation.
Le constructeur de Personne (classe de base) est appelé avant le
constructeur de Etudiant (classe dérivée).
// Classe de base
class Personne {
private: string nom;
public:
Personne(string n) { nom = n }
};
// Classe dérivée
class Etudiant : public Personne {
private: string ine;
public:
Etudiant(string nom, string ine) : Personne(nom), ine(ine) { }
};
Propriétés de la généralisation
Héritage multiple
Définitions
On déclare qu’on veut une fonction qui ait la flexibilité des propriétés
de l’association tardive en utilisant le mot-clé virtual.
On n’a pas besoin de comprendre les mécanismes de virtual pour
l’utiliser, mais sans lui on ne peut pas faire de la programmation
orientée objet en C++.
En C++, on doit se souvenir d’ajouter le mot-clé virtual (devant
une méthode) parce que, par défaut, les fonctions membres ne sont
pas liées dynamiquement. Les fonctions virtuelles permettent
d’exprimer des différences de comportement entre des classes de la
même famille.
Ces différences sont ce qui engendre un comportement polymorphe.
class Forme {
public:
Forme() { cout << "constructeur Forme <|- "; }
void dessiner() { cout << "je dessine ... une forme ?\n"; }
};
int main()
{
Cercle c;
Triangle t;
return 0;
}
class Forme {
public:
Forme() { cout << "constructeur Forme <- "; }
// la méthode dessiner sera virtuelle et fournira un comportement polymorphe
virtual void dessiner() { cout << "je dessine ... une forme ?\n"; }
};
int main()
{
Cercle c;
Triangle t;
return 0;
}
class A {
private: int *p;
public:
A() {p = new int[4]; cout << "A()";}
~A() {delete [] p; cout<< " ~A()" << endl;}
};
class B : public A {
private: int *q;
public:
B() {q = new int[64]; cout<< "B() et q=" << q;}
~B() {delete [] q; cout<< " ~B()";}
};
int main() {
A *pA = new B(); delete pA; // A()B() et q=0x100170 ~A()
}
class A {
private: int *p;
public:
A() {p = new int[4]; cout << "A()";}
virtual ~A() {delete [] p; cout<< " ~A()" << endl;}
};
class B : public A {
private: int *q;
public:
B() {q = new int[64]; cout<< "B() et q=" << q;}
~B() {delete [] q; cout<< " ~B()";}
};
int main() {
A *pA = new B(); delete pA; // A()B() et q=0x100170 ~B() ~A()
}
// Une classe dans laquelle il n’y a plus une seule fonction virtuelle pure est
dite concrète et devient instanciable
class Cercle : public Forme {
public:
Cercle() {}
void dessiner() { cout << "je dessine un Cercle !\n"; }
};
Le transtypage en C++
Transtypage « ascendant »
Traiter un type dérivé comme s’il était son type de base est appelé
transtypage ascendant, surtypage ou généralisation (upcasting). Cela ne
pose donc aucun problème.
Exemple : transtypage « ascendant »
class Forme {};
class Cercle : public Forme {};
class Triangle : public Forme {} ;
...
Cercle c;
// Un Cercle est ici passé à une fonction qui attend une Forme.
// Comme un Cercle est une Forme, il peut être traité comme tel par
faireQuelqueChose()
faireQuelqueChose(c);
Transtypage « descendant »
Conversion d’un pointeur sur un objet d’une classe générale vers un objet
d’une classe spécialisée.
Exemple : transtypage « ascendant »
class Animal { public: virtual ~Animal() {} };
class Chien : public Animal {};
class Chat : public Animal {};
int main() {
Animal* a = new Chat; // Transtypage ascendant