Chapitre 7 : Polymorphisme A.U.
: 2009/2010
ENSI – II2
Exemple d’héritage
Polymorphisme ObjetGeo
Introduction
Conversion d’objets et trans-
trans-typage Sphere Cube Cylindre
Fonction virtuelle
Fonction virtuelle pure
Classe abstraite • ObjetGeo: Super-
Super-classe ou classe de base. Classe
Structure Polymorphe très générale.
Destructeur virtuel
Exemples • Sphere, Cube, Cylindre: classe dérivée. Classes
plus spécifiques.
spécifiques.
1 2
Conversion d’objets Conversion d’objets (suite)
Un objet de la classe dérivée ObjetGeo UnObjet; Un pointeur (ou une référence) sur un objet de la classe
peut--être converti implicitement
peut Cube MonCube; dérivée peut-
peut-être converti implicitement en un pointeur
en un objet de la classe de de la classe de base. (upcasting)
base. UnObjet = MonCube;
ObjetGeo * PtrObjet; Cube monCube;
class A
{ protected :int i; PtrObjet = new Cube; ObjetGeo & obj = monCube;
A a;
public: 2
int f(){return(2
f(){return(2*i);}
a.f();
…}; A * ptrA @
B b;
class B : public A
b.f();
{ int j;
3
public: a = b; B* ptrB @
int f(){return(i*j);} 4
a.f();
…};
3 4
Conversion d’objet (suite) Que se passe t-
t-il ?
Un pointeur d’une classe de base pointe ou référence une
Une conversion de la classe de base vers la instance dynamique de la classe dérivée. (PtrObjet pointe
classe dérivée n’est pas autorisée. vers un espace mémoire de type Cube)
Polymorphisme = plusieurs formes
ObjetGeo MonObjet;
A partir du pointeur PtrObjet, on ne peut accèder qu’à
Cube MonCube; l’interface public de la classe ObjetGeo.
MonCube = MonObjet; Dans le cas où la classe dérivée redéfinit les méthodes de
la classe de base, doit-
doit-on invoquer les méthodes de la
classe dérivée ou de la classe de base.
En cas de besoin, il faut créer la surcharge
de l’opérateur =(ObjetGeo &) dans la classe deux cas : sans virtualité ou avec virtualité
MonCube
5 6
1
Chapitre 7 : Polymorphisme A.U. : 2009/2010
ENSI – II2
Fonction virtuelle La classe ObjetGeo
La fonction virtuelle est utilisée afin de permettre class ObjetGeo
l'utilisation d'objets de façon appropriée dans un { Fonction virtuelle
programme où le type des objets n'est pas connu à la Position P;
compilation. afficher()
public:
ObjetGeo();
Le mot clé virtual indique que la fonction peut avoir virtual void afficher();
différentes versions pour les différentes classes dérivées. . . .
};
Lors de l’exécution du programme, la bonne version de void ObjetGeo::afficher()
fonction est exécutée dynamiquement.
{
Liaison dynamique (virtualité) cout << "Position " << P << endl;
}
7 8
La classe Sphere dérivée de la classe
ObjetGeo Portée de la virtualité
class Sphere : public ObjetGeo Redéfinition de la méthode
{ afficher() dans la classe Sphere. virtual f();
public: g();
Sphere(int r);
void afficher(); ObjetGeo *ptr;
private:
ptr=new Sphere(7); virtual f();
float rayon; virtual g();
ptr-
ptr ->afficher();
};
void Sphere::afficher()
{
ObjetGeo::afficher(); f();
f(); f();
cout << "Rayon: " << rayon << endl; g();
}
9 10
Destructeur virtuel Destructeur virtuel (exemple)
ObjetGeo *OB = new Cube();
Un destructeur peut être défini comme virtuel.
Cependant, un constructeur ne pourra jamais l’être. class ObjetGeo { class ObjetGeo {
Contexte public: public:
~ ObjetGeo
ObjetGeo();
();
Destruction d’un objet de la classe dérivée qui est ~ virtual ObjetGeo
ObjetGeo();
();
};
}; class Cube {
référencé par un pointeur de la classe de base, class Cube {
public: public:
Résultat ~ Cube(); ~ Cube();
Si le destructeur est virtuel }; };
alors le destructeur de la classe dérivée est appelé . delete OB;
Sinon seul le destructeur de la classe de base est
appelé. Le destructeur de Cube est appelé en premier seul le destructeur de
+ le destructeur de ObjetGeo sera appelé. ObjetGeo sera appelé.
11 12
2
Chapitre 7 : Polymorphisme A.U. : 2009/2010
ENSI – II2
Fonction virtuelle pure et classe
Fonction virtuelle pure
abstraite
Certaines classes représentent des concepts abstraits par class ObjetGeo
lesquels des objets ne peuvent jamais exister. { . . .
public:
Exemple: Un objet géométrique
géométrique ne peut exister sans savoir . . .
comment sa forme est représentée. virtual float volume() = 0;
protected
On déclare des fonctions virtuelles pures par un Position P;
initialisateur = 0. };
class Cube : public ObjetGeo class Sphere : public ObjetGeo
Une classe qui possède une fonction virtuelle pure { float Larg,Long,Haut; { int rayon;
est une classe abstraite et ne peut donc jamais public: public:
être instanciée float volume(){ float volume(){
return (Larg * Long *Haut); return ((4/3)*rayon^3*PI);
Les classes dérivées implémentent à leur niveau ces fonctions. } }
}; };
13 14
Exemple 1 :
Classe abstraite Recherche dans une table
Une classe abstraite sert pour factoriser. Aussi, elle joue le Variantes d’implémentation => classe abstraite + des classes dérivées
rôle d’une interface commune à plusieurs implémentation.
La classe abstraite ne peut pas être passée en paramètre
comme objet statique.
TABLE
La classe abstraite peut cependant être passée par
pointeur ou par référence (polymorphisme). TABLE TABLE ARBRE
INDEXE SEQUENTIELLE BINAIRE
Attention ! Les sous-
sous-classes d’une classe abstraite doivent
implémenter ces fonctions virtuelles pures, sinon elles aussi TABLEAU LISTE CHAINEE FICHIER
deviennent abstraites. D’ENREGISTREMENT
15 16
Recherche séquentielle :
Exemple 1 (suite) variantes d'implémentation
class Table bool Table::rechercher(X x) Tableau Liste Fichier
{ { Chaînée Séquentiel
public: début Début de la recherche : i = 1 1 = tête ouvrir
bool rechercher(X x); demarrer(); Position_initiale
while (!fin() && !trouve(x)) Lecture
virtual void demarrer()
demarrer() = 0;
virtual void avancer() = 0; avancer();
virtual bool trouve() = 0; return ( !fin() ); Avancer à la position
}; suivante : Avancer i = i + 1 lire(enreg)
virtual bool fin() = 0; l= l.suivant
};
class Tableau : public Table class Liste : public Table
{ X t[MAX]; { struct element { Comparaison : t[i] == x l.valeur== x Enreg == x
public: X valeur; Trouvé
void demarrer() ; element * suivant;
} * tete; Test de fin de i > taille 1 == null Eof
void avancer();
public: parcours : Epuisé
bool trouve();
bool fin() ; // demarrer(); avancer(); trouve(); fin();
}; };
17 18
3
Chapitre 7 : Polymorphisme A.U. : 2009/2010
ENSI – II2
Structure Polymorphe =
Collection d’objets d’une classe de base comportant des
Exemple 1 (suite) méthodes virtuelles
Soit ObjetGeo *Tab[N];
Tab est rempli d’objets de type Sphere et/ou Cube
float Somme=0;
for(i=0; i<N; i++)
Tableau Somme+=Tableau[i]-
Somme+=Tableau[i]->volume
volume();
();
Table * T;
T = new …
…
T->rechercher(x);
Liste
Application
19 20
Version Orientée objets :
La Réservation Aérienne traitée dans le
L’opérateur typeid chapitre 1.
l’opérateur typeid permet de connaître le type d’un 1..N
objet lors de l’exécution Application Ecran
ObjetGeo *Tab[N];
int nbCube=0
nbCube=0;
for(i=0
for(i= 0; i<N; i++)
if ( typeid
typeid(( Tableau[i] ) == typeid
typeid(( Cube)) Initial Rech_Vols Rech_Place Réservation
nbCube++;
Attention: il faut éviter le plus possible d’utiliser cet opérateur
21 22
Réservation aérienne (suite) Réservation aérienne (suite)
class Application
{ Ecran * tab[10]; // l’ensemble des écrans class Ecran{
private: void ecran::execute(){
int T[10][10]; // automate = 10 écrans + 10 choix afficher();
int choix;
public: lire();
public:
void ajouter(Ecran *e, int pos) {T[pos]=e;} void executer(); if (!correct()) {
void setTransition(int src, int choix, int dest) virtual void lire(); message();
virtual bool correct() const; execute();
{ T[src][choix] = dest; }
virtual void afficher()=0; }
int getTransition(int src, int choix) }
virtual void message();
{ return T[src][choix]; } void ecran::lire(){ cin>>choix; }
int getChoix() const;
void run() void main(){ };
{ Ecran * courant; Application a; bool ecran::correct() const{
courant= T[1]; return ((choix==0)||(choix==2)||
class Initial : public Ecran (choix==3));
while (courant != null){ a.construire(); {
courant-
courant ->execute(); }
public: . . .
courant=getTransition(courant, a.run(); . . . ;
courant-
courant ->getChoice()); } } };
}
};
23 24