Académique Documents
Professionnel Documents
Culture Documents
ENSI - II1
Chapitre 5 : Héritage & Polymorphisme en C++ A.U. : 2012/2013
CHAPITRE 5
Plan
2
Héritage
Principe de l’héritage
Visibilité des membres
Redéfinition des membres
Constructeur et destructeur
Constructeur de recopie et héritage
Opérateur d’affectation et héritage
Types d’héritage
Héritage multiple
Plan
3
Polymorphisme
Compatibilité classe de base / classe dérivée
Typage statique / Typage dynamique
Fonctions virtuelles
Destructeur virtuel
Fonctions virtuelles pures et classes abstraites
Structures polymorphes
L’opérateur typeid
Principe de l’héritage
4
Généralisation
2 types d’héritage :
Héritage simple : la classe dérivée ne peut hériter que d’une seule
classe de base.
Héritage multiple : la classe dérivée peut hériter de plusieurs classes
de base.
Principe de l’héritage
5
Principe de l’héritage
6
Principe de l’héritage
7
Principe de l’héritage
8
Principe de l’héritage
9
Membres protégés
Niveau de visibilité protected : les membres protégés de la
classe de base sont accessibles à ses classes dérivées mais pas à
ses utilisateurs.
class Point x et y sont des attributs
{
protégés de la classe Point.
protected:
Ils sont donc accessibles
int x, y;
public : aux classes dérivées de
void initialiser(int, int); Point mais pas aux
void deplacer(int, int); utilisateurs de la classe
void afficher(); Point ni aux utilisateurs de
}; ses classes dérivées.
Membres protégés
class PointCol : public Point
{ short couleur; L’accès aux attributs x et y est
public : possible à partir de la classe
void colorer (short cl) PointCol car cette dernière est une
{ couleur = cl; }
classe dérivée de la classe point. On
void afficher_c();
};
n’a plus besoin de passer par les
void PointCol::afficher_c() méthodes publiques pour ce faire.
{
cout << "Coordonnees : " << x << "," << y << endl;
cout << "Couleur : " << couleur << endl;
}
Récapitulation
class A class B : public A int main()
{ { {
private: public: A a;
int i; void f() a.i = 0;
public: { a.j = 0;
int j; i = 0; a.k = 0;
protected: j = 0; }
int k; k = 0;
}; }
};
Constructeur et destructeur
21
Constructeur et destructeur
22
Constructeur et destructeur
23
Constructeur et destructeur
24
Constructeur et destructeur
25
Constructeur et destructeur
26
Si l'on souhaite que PointCol transmette à Point les deux premiers paramètres
reçus, on écrira son en-tête de cette manière :
PointCol (int abs, int ord, short cl) : Point (abs, ord)
Le compilateur mettra en place la transmission au constructeur de Point des
paramètres abs et ord correspondant aux deux premiers arguments de PointCol.
Ainsi, la déclaration : PointCol a (10, 15, 3) ; entraînera :
• l'appel de Point qui recevra les arguments 10 et 15
• l'appel de PointCol qui recevra les arguments 10, 15 et 3
Rappel
Le constructeur de recopie est appelé en cas :
d'initialisation d'un objet par un objet de même type.
de transmission de la valeur d'un objet en argument.
En cas d’héritage
2 cas se présentent :
La classe dérivée ne définit pas de constructeur de recopie.
La classe dérivée définit un constructeur de recopie.
Rappel
L’affectation d’objets s’effectue membre à membre de manière
superficielle. Pour effectuer une copie profonde (en cas de
présence d’attributs dynamiques), l’opérateur = est surchargé
sous la forme d’une méthode de la classe concernée.
En cas d’héritage
2 cas se présentent :
La classe dérivée ne surcharge pas l’opérateur d’affectation.
La classe dérivée surcharge l’opérateur d’affectation.
Types d’héritage
34
Types d’héritage
35
Héritage public
class ClasseDerivee : public ClasseBase
Types d’héritage
36
Héritage privé
class ClasseDerivee : private ClasseBase
Types d’héritage
37
Héritage protégé
class ClasseDerivee : protected ClasseBase
Héritage multiple
38
Héritage multiple
39
Héritage multiple
40
Héritage multiple
41
Héritage multiple
42
Conversion d’objets
Soit les deux classes Point et PointCol qui en dérive et les
déclarations :
Point a;
PointCol b;
l'affectation a = b est légale. Elle entraîne une conversion de b
dans le type Point et l'affectation du résultat à a.
Conversion de pointeurs
Soit les deux classes Point et PointCol qui en dérive et les
déclarations :
Point* adp;
PointCol* adpc;
l'affectation adp = adpc est légale. Elle correspond à une
conversion du type PointCol* dans le type Point*.
Limitations
Soit les déclarations suivantes :
Point p(3, 5); PointCol pc(8, 6, 2);
adp = &p; adpc = &pc;
Limitations
Suite à cette affectation : adp = adpc;
Limitations
Nous pouvons désigner, à l'aide d'un même pointeur, des objets
de types différents, mais nous n'avons pour l'instant aucun moyen
de tenir réellement compte du type de l'objet pointé.
Fonctions virtuelles
49
Fonctions virtuelles
50
Fonctions virtuelles
51
Exemple 1
class Point
{ protected:
int x, y;
public:
Point(int abs=0, int ord=0)
{ x=abs; y=ord; }
virtual void afficher()
{ cout<<"Je suis un point de coordonnees : "<<x<<" "<<y<<"\n"; }
};
class PointCol : public Point
{ short couleur;
public:
PointCol(int abs=0,int ord=0,short cl=1) : Point (abs, ord)
{ couleur = cl; }
void afficher()
{ cout<<"Je suis un point colore de coordonnees : "<<x<<" "<<y;
cout<<" et de couleur : "<<couleur<< "\n";
}
};
Fonctions virtuelles
52
Exemple 1
int main()
{ Point p(3,5); Point* adp = &p;
PointCol pc(8,6,2); PointCol* adpc = &pc;
adp->afficher();
adpc->afficher();
cout << "-----------------\n" ;
adp = adpc;
adp->afficher();
adpc->afficher();
}
Fonctions virtuelles
53
Exemple 2
class ObjetGeo
{ Position P; ObjetGeo *ptr;
public: ptr = new Sphere(7);
ObjetGeo(); ptr->afficher();
virtual void afficher()
{ cout << "Position " << P << endl; }
. . . ptr->afficher() provoque
}; l’appel de la méthode
afficher() redéfinie de la
class Sphere : public ObjetGeo
{ float rayon; classe Sphere malgré que
public: le pointeur ptr est à la base
Sphere(int r); est pointeur de type
void afficher()
ObjetGeo. Il s’agit du
{ ObjetGeo::afficher();
cout << "Rayon: " << rayon << endl; typage dynamique réalisé
} grâce à l’utilisation de la
}; virtualité.
Fonctions virtuelles
54
Restrictions
Seules les méthodes d’une classe peuvent être virtuelles.
Destructeur virtuel
55
Contexte :
Destruction d’un objet de la classe dérivée, qui est référencé par
un pointeur de la classe de base.
Résultat :
Si le destructeur de la classe de base est virtuel
alors le destructeur de la classe dérivée sera appelé d’abord,
celui de la classe de base sera appelé ensuite.
Sinon seul le destructeur de la classe de base est appelé.
Destructeur virtuel
56
Exemple :
ObjetGeo *OB = new Cube();
class ObjetGeo class ObjetGeo
{ public: { public:
~ virtual ObjetGeo(); ~ ObjetGeo();
... ...
}; };
delete OB;
Une classe qui possède une fonction virtuelle pure est une classe
abstraite et ne peut donc pas être instanciée.
class ObjetGeo
Classe abstraite
{ protected:
Position P; Fonction virtuelle pure
public:
. . .
virtual float volume() = 0;
};
Structure polymorphe
59
float Somme=0;
for(i=0; i<N; i++)
Somme += Tab[i]->volume();
L’opérateur typeid
60
ObjetGeo *Tab[N];
int nbCube = 0;
for(i = 0; i < N; i++)
if ( typeid(Tableau[i]) == typeid(Cube))
nbCube++;