88
Chapitre VI Chapitre VI Polymorphisme (Vient du grec et signifie « Peut prendre plusieurs formes ») Exemple : Imaginons un jeu d’échec comportant des objets fou, roi, t La méthode « mouvement() » pourra, grâce au polymorphisme, effectuer le mouvement approprié d’une pièce grâce au type qui lui sera associé. une variable déclarée comme pointeur vers un type de base de ur d’un type dérivé.

Chapitre VI

  • Upload
    luther

  • View
    21

  • Download
    0

Embed Size (px)

DESCRIPTION

Chapitre VI. Permet à une variable déclarée comme pointeur vers un type de base de contenir une valeur d’un type dérivé. Polymorphisme (Vient du grec et signifie « Peut prendre plusieurs formes »). Imaginons un jeu d’échec comportant des objets fou, roi, tour, … - PowerPoint PPT Presentation

Citation preview

Page 1: Chapitre VI

Chapitre VIChapitre VI

Polymorphisme(Vient du grec et signifie « Peut prendre plusieurs formes »)

Exemple : Imaginons un jeu d’échec comportant des objets fou, roi, tour, …

La méthode « mouvement() » pourra, grâce au polymorphisme,effectuer le mouvement approprié d’une pièce grâce au type de piècequi lui sera associé.

Permet à une variable déclarée comme pointeur vers un type de base de contenirune valeur d’un type dérivé.

Page 2: Chapitre VI

Chapitre VI - Polymorphisme 2

Pointeurs d’une classe de base vs Pointeurs d’une classe de base vs pointeurs de classes dérivéespointeurs de classes dérivées

Héritage et pointeur de base

On peut définir un pointeur vers une classe de base pour stocker l’adresse d’objetsdérivés.Si les classes B et et C dérivent de A, on peut définir un pointeur vers la classe Apour stocker soit l’adresse d’un objet de type B soit l’adresse d’un objet de type C.

Ex.: Polygone_2D * P;P = new Polygone_2D;delete P;

P = new Polygone_2D_convexe;delete P;Cette affectation est possible uniquement parce que la classePolygone_2D_convexe dérive de la classe Polygone_2D.

Page 3: Chapitre VI

Chapitre VI - Polymorphisme 3

Pointeurs d’une classe de base vs Pointeurs d’une classe de base vs pointeurs de classes dérivéespointeurs de classes dérivées

Attention Le sens d’affectation est primordial. C++ ne permet pas de stocker l’adressed’un objet de type Polygone_2D dans un pointeur Polygone_2D_convexe.

IntérêtIl est possible de déclarer une seule variable de type pointeur puis choisir aumoment de l’exécution du programme le type d’objet à créer.

IntérêtPour gérer des ensembles d’objets, il suffit de définir un tableau de pointeursvers la classe de base pour stocker l’adresse de n’importe quel objet dérivé.

Ex.: On peut définir un tableau de pointeurs vers des polygones, des polygonesconvexes et des triangles.

Polygone_2D * Tableau[20];

On peut effectuer un forçage de type explicite pour convertir un pointeur de classede base en un pointeur de classe dérivée (voir exemples).

Collection hétérogène

Page 4: Chapitre VI

Chapitre VI - Polymorphisme 4

Substitution des fonctions membres d’une Substitution des fonctions membres d’une classe de base dans une classe dérivéeclasse de base dans une classe dérivée

La substitution est faite en fournissant une nouvelle version de cette fonction avecla même signature.

Note : Une signature différente => une surcharge de fonction et non unesubstitution de fonction.

En mentionnant cette fonction par son nom dans la classe dérivée, la version de laclasse dérivée est choisie automatiquement.

On peut utiliser l’opérateur de résolution de portée (::) pour accéder à la version dela classe de base à partir de la classe dérivée.

Par ex., il arrive souvent que la version de la classe dérivée appelle la versionde la classe de base en plus d’effectuer certains travaux additionnels.

Page 5: Chapitre VI

Chapitre VI - Polymorphisme 5

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

#include <iostream.h>

typedef enum {insecte = 0, vent, animal, eau, humain} mode_de_pollinisation;

typedef enum{guepe, coccinelle, mouche, libellule, cigale, abeille, fourmi, sauterelle, patineur}

type_insecte;

class Pollinisation{

protected : mode_de_pollinisation Mode;public : Pollinisation(mode_de_pollinisation M);

mode_de_pollinisation Acces_mode();void Clone(Pollinisation P);

};

Page 6: Chapitre VI

Chapitre VI - Polymorphisme 6

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

Pollinisation::Pollinisation(mode_de_pollinisation M){

Mode = M;cout << "Constructeur de la classe de base: " << Mode << endl;

}

mode_de_pollinisation Pollinisation::Acces_mode(){

return Mode;}void Pollinisation::Clone(Pollinisation P){

Mode = P.Acces_mode();cout << "Mode : " << Mode << endl;

}

Page 7: Chapitre VI

Chapitre VI - Polymorphisme 7

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

class Pollinisation_par_insecte : public Pollinisation{

private : type_insecte Nom_d_insecte;public : Pollinisation_par_insecte(type_insecte Nom);

type_insecte Acces_nom();void Clone(Pollinisation_par_insecte P);

};Pollinisation_par_insecte::Pollinisation_par_insecte(type_insecte Nom)

:Pollinisation(insecte){

Nom_d_insecte = Nom;cout << "Constructeur de la classe derivee: " << Nom_d_insecte << endl;

}type_insecte Pollinisation_par_insecte::Acces_nom(){ return Nom_d_insecte; }

Page 8: Chapitre VI

Chapitre VI - Polymorphisme 8

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

void Pollinisation_par_insecte::Clone(Pollinisation_par_insecte P){

Nom_d_insecte = P.Acces_nom();cout << "Nom : " << Nom_d_insecte << endl;Pollinisation::Clone(P);

}void main(){

Pollinisation P(vent);Pollinisation Q(eau);Q.Clone(P);

Pollinisation_par_insecte R(abeille);Pollinisation_par_insecte S(cigale);R.Clone(S);

Page 9: Chapitre VI

Chapitre VI - Polymorphisme 9

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

P.Clone(S);

Pollinisation_par_insecte * T = new Pollinisation_par_insecte(fourmi);((Pollinisation *) T) -> Clone(Q);((Pollinisation *) T) -> Clone(S);

// T -> Clone(Q); Conversion de Q impossible.T -> Clone(S);

Pollinisation * U = new Pollinisation(insecte);// ((Pollinisation_par_insecte *) U) -> Clone(Q); Conversion de Q impossible.

((Pollinisation_par_insecte *) U) -> Clone(S);U -> Clone(Q);U -> Clone(S);

}

Page 10: Chapitre VI

Chapitre VI - Polymorphisme 10

Forçage de types explicites et Forçage de types explicites et substitution des fonctions membressubstitution des fonctions membres

Constructeur de la classe de base: 1 Mode : 0Constructeur de la classe de base: 3 Constructeur de la classe de base: 0Mode : 1 Nom : 4Constructeur de la classe de base: 0 Mode : 0Constructeur de la classe dérivée: 5 Mode : 1Constructeur de la classe de base: 0 Mode : 0Constructeur de la classe dérivée: 4Nom : 4Mode : 0Mode : 0Constructeur de la classe de base: 0Constructeur de la classe dérivée: 6Mode : 1Mode : 0Nom : 4

Page 11: Chapitre VI

Chapitre VI - Polymorphisme 11

Exemple : classe PileExemple : classe Pile (Pile.h)(Pile.h)

class element{};class pile{/* Spécification fonctionnelle de la classe " pile ".Éléments : Chaque sommet de la pile renferme l'adresse d'un élément,

non pas l'élément lui-même où le type de chaque élémentest une classe dérivée de la classe de base "element".

Structure : Les éléments sont reliés entre eux permettant dedéterminer l'ordre d'arrivée des éléments dans la pile. */

Page 12: Chapitre VI

Chapitre VI - Polymorphisme 12

Exemple : classe PileExemple : classe Pile (Pile.h)(Pile.h)

protected:struct sommet_pile{

element * pElement;struct sommet_pile *suivant;

};

struct sommet_pile * pPile;

Page 13: Chapitre VI

Chapitre VI - Polymorphisme 13

Exemple : classe PileExemple : classe Pile (Pile.h)(Pile.h)

public:void Creer_pile();/* Permet de créer une pile vide.

Pré - Nil.Post - La pile existe et est vide. */

void Inserer(element * pElement);/* Insérer l'adresse d'un élément dans la pile.

Pré - La pile a déjà été créée et n'est pas pleine.Post - La pile renferme pElement et l'interprète comme étant

l'adresse de l'élément le plus récent inséré dans la pile */

Page 14: Chapitre VI

Chapitre VI - Polymorphisme 14

Exemple : classe PileExemple : classe Pile (Pile.h)(Pile.h)

element * Enlever();/* Enlever un élément de la pile.

Pré - La pile a déjà été créée et n'est pas vide.Post - L'adresse de l'élément le plus récent inséré dans la pile

est retourné; cet élément ne fait plus partiede la pile. */

bool Pile_vide();/* Vérifier si la pile est vide ou non.

Pré - La pile a déjà été créée.Post - Si la pile ne possède aucun élément

alors retourner truesinon retourner false. */

Page 15: Chapitre VI

Chapitre VI - Polymorphisme 15

Exemple : classe PileExemple : classe Pile (Pile.h)(Pile.h)

bool Pile_pleine();/* Vérifier si la pile est pleine ou non.

Pré - La pile a déjà été créée.Post - Si la pile a atteint sa capacité maximale

alors retourner vraisinon retourner faux. */

void Vider_pile();/* Vider la pile.

Pré - La pile a déjà été créée.Post - La pile est vide. */

};

Page 16: Chapitre VI

Chapitre VI - Polymorphisme 16

Exemple: classe Pile Exemple: classe Pile (Pile.cpp)(Pile.cpp)

#include <iostream.h>#include "Pile.h"void pile::Creer_pile(){

pPile = NULL;}void pile::Inserer(element * pElement){

struct sommet_pile *pe = new sommet_pile;(*pe).pElement = pElement;(*pe).suivant = pPile;pPile = pe;

}

Page 17: Chapitre VI

Chapitre VI - Polymorphisme 17

Exemple : classe Pile Exemple : classe Pile (Pile.cpp)(Pile.cpp)

element * pile::Enlever(){

element * pElement;struct sommet_pile *pe = NULL;

pElement = (*pPile).pElement;pe = pPile;pPile = (*pPile).suivant;delete(pe);return pElement;

}

Page 18: Chapitre VI

Chapitre VI - Polymorphisme 18

Exemple : classe Pile Exemple : classe Pile (Pile.cpp)(Pile.cpp)

bool pile::Pile_vide(){

if (pPile == NULL ) return true;else return false;

}bool pile::Pile_pleine(){

/* Il n'y a aucune façon de tester si la liste chaînée estpleine i.e. s'il existe encore de l'espace disponible pourun autre sommet "sommet_pile". */

return false;}

Page 19: Chapitre VI

Chapitre VI - Polymorphisme 19

Exemple : classe Pile Exemple : classe Pile (Pile.cpp)(Pile.cpp)

void pile::Vider_pile(){

element * pElement;

while (Pile_vide() == false) pElement = Enlever();}

Page 20: Chapitre VI

Chapitre VI - Polymorphisme 20

Utilisation de plusieurs pilesUtilisation de plusieurs piles

#include <iostream.h>#include "pile.h"class entier: public element{

public:int e;

};class reel: public element{

public:float r;

};

class caractere: public element{

public:char c;

};

Page 21: Chapitre VI

Chapitre VI - Polymorphisme 21

Utilisation de plusieurs pilesUtilisation de plusieurs piles

void main(){

entier i, j, k;reel a, b;caractere u;i.e = 0; j.e = 1; k.e = 2;a.r = 0.0f; b.r = 0.1f;u.c = 'a';pile Pile_entiers, Pile_reels, Pile_caracteres;Pile_entiers.Creer_pile();Pile_reels.Creer_pile();Pile_caracteres.Creer_pile();

Page 22: Chapitre VI

Chapitre VI - Polymorphisme 22

Utilisation de plusieurs pilesUtilisation de plusieurs piles

Pile_entiers.Inserer(&i);Pile_entiers.Inserer(&j);Pile_entiers.Inserer(&k);Pile_reels.Inserer(&a);Pile_reels.Inserer(&b);Pile_caracteres.Inserer(&u);cout << (* (entier *) Pile_entiers.Enlever()).e;cout << (* (entier *) Pile_entiers.Enlever()).e;cout << (* (entier *) Pile_entiers.Enlever()).e;cout << (* (reel *) Pile_reels.Enlever()).r;cout << (* (reel *) Pile_reels.Enlever()).r;cout << (* (caractere *) Pile_caracteres.Enlever()).c;

Page 23: Chapitre VI

Chapitre VI - Polymorphisme 23

Utilisation de plusieurs pilesUtilisation de plusieurs piles

if ((Pile_entiers.Pile_vide() == true) &&(Pile_reels.Pile_vide() == true) &&(Pile_caracteres.Pile_vide() == true))

cout << "Les 3 piles sont vides.";

}

Page 24: Chapitre VI

Chapitre VI - Polymorphisme 24

Une pile de dossiersUne pile de dossiers

#include <iostream.h>#include <string.h>#include "pile.h"class dossier: public element{

protected:int code; char description[20+1]; float priorite;

public:dossier(int c, char * d ="", float p = 0.0f);int Acces_Code();char * Acces_Description();float Acces_Priorite();

};

Page 25: Chapitre VI

Chapitre VI - Polymorphisme 25

Une pile de dossiersUne pile de dossiers

dossier::dossier(int c, char * d, float p){

code = c;priorite = p;strcpy(description, d);

}

int dossier::Acces_Code(){

return code;}

Page 26: Chapitre VI

Chapitre VI - Polymorphisme 26

Une pile de dossiersUne pile de dossiers

char * dossier::Acces_Description(){

return description;}

float dossier::Acces_Priorite(){

return priorite;}

Page 27: Chapitre VI

Chapitre VI - Polymorphisme 27

Une pile de dossiersUne pile de dossiers

void main(){

dossier c(36);dossier b(12, "description I : ", 0.25);dossier a(24, "description II : ");pile Pile_dossiers;Pile_dossiers.Creer_pile();

Pile_dossiers.Inserer(&a);Pile_dossiers.Inserer(&b);Pile_dossiers.Inserer(&c);

Page 28: Chapitre VI

Chapitre VI - Polymorphisme 28

Une pile de dossiersUne pile de dossiers

cout << (* (dossier *) Pile_dossiers.Enlever()).Acces_Code();cout << (* (dossier *) Pile_dossiers.Enlever()).Acces_Description();cout << (* (dossier *) Pile_dossiers.Enlever()).Acces_Priorite();

if (Pile_dossiers.Pile_vide() == true)cout << "La pile est vide.";

}

FIN

Page 29: Chapitre VI

Chapitre VI - Polymorphisme 29

Une forêt, pas un arbreUne forêt, pas un arbre

Certains langages de programmation orientés objet (comme par ex. Smalltalk et Java)placent tous les objets dans une unique grande hiérarchie d’héritage :

Tous les objets dans ces langages descendent d’une unique classede base nommée le plus souvent Object.

Avantages : Un pointeur vers un objet de cette classe peut renfermertout type de valeur.

Tout comportement défini dans la classe Object est communà toutes les classes.

Le langage C++ ne procède pas ainsi; il permet aux programmeurs de créer uneforêt de nombreux petits arbres d’héritage.

Page 30: Chapitre VI

Chapitre VI - Polymorphisme 30

PolymorphismePolymorphisme

Pourquoi les notions d’héritage et de pointeurs de base ne peuvent s’appliquer à laconstruction de la classe Vecteur pour éliminer la surcharge de fonctions?

INTÉRÊT Technique associée au polymorphisme: la redéfinition des fonctionsmembres des classes.

Le polymorphisme permet à des objets de classes différentes liées par héritagede répondre de façon distincte à un appel de fonction membre.

Page 31: Chapitre VI

Chapitre VI - Polymorphisme 31

Exemple permettant Exemple permettant d’introduire le polymorphismed’introduire le polymorphisme

Tiré de [Dupin, 99; pp. 247-253]

#include <iostream.h>#include <string.h>

class materiel{

protected:char Reference[20+1];char Marque[20+1];

public:Materiel(char *r, char *m);void Affiche();

};

class Micro : public Materiel{

protected:char Processeur[20+1];int Disque;

public:Micro(char *r, char *m,

char *p, int d);void Affiche();

};

Page 32: Chapitre VI

Chapitre VI - Polymorphisme 32

Exemple permettant Exemple permettant d’introduire le polymorphismed’introduire le polymorphisme

Materiel::Materiel(char *r, char *m){

strcpy(Reference, r);strcpy(Marque, m);

}

void Materiel::Affiche(){

cout << "Ref : "   << Reference;cout << "Marque : "   << Marque;cout <<   "\n";

}

Micro :: Micro(char *r, char *m,char *p, int d)

:Materiel(r,m){

strcpy(Processeur, p);Disque = d;

}void Micro::Affiche(){

cout << "Ref : "   << Reference; cout << "Marque : "   << Marque; cout << "Proc : "   << Processeur; cout << "Disque : "   << Disque; cout <<   "\n";

}

Page 33: Chapitre VI

Chapitre VI - Polymorphisme 33

Exemple permettant Exemple permettant d’introduire le polymorphismed’introduire le polymorphisme

int main(){

Materiel *pMat;pMat = new Materiel("X01", "XX");pMat -> Affiche();delete pMat;

pMat = new Micro("X16",  "PH",   "DX4-100", 200);pMat -> Affiche();delete pMat;

return 0;}

Ref : X01 Marque : XXRef : X16 Marque : PH

Page 34: Chapitre VI

34

Exemple permettant Exemple permettant d’introduire le polymorphismed’introduire le polymorphisme

Erreur Les 2 classes possèdent une fonction Affiche().

Le résultat affiché est invalide car c’est la méthode Affiche() deMateriel qui a été utilisée chaque fois.

Pourquoi? Le compilateur a tenu compte du type de pointeur(Materiel *) et non pas du type d’objet pointé par pMat.

Comportement non polymorphique

Il arrive qu’une fonction membre non virtual soit définie dans une classe de base etredéfinie dans une classe dérivée.

Si on appelle cette fonction par un pointeur de classe de base vers l’objet de classedérivée, la version de classe de base est alors utilisée.

Si on appelle cette fonction au moyen d’un pointeur de classe dérivée, la versionutilisée est alors celle de classe dérivée.

Page 35: Chapitre VI

35

Exemple permettant Exemple permettant d’introduire le polymorphismed’introduire le polymorphisme

Solution Il faudrait que le compilateur appelle la fonction Affiche() de Micro(resp. Materiel) quand pMat contient l’adresse d’un objet de typeMicro (resp. Materiel).

Il faut indiquer au compilateur que la fonction Affiche() est unefonction polymorphe, i.e. en C++, une fonction virtuelle.

Il suffit de faire précéder son prototype par le mot clé virtual.

Il n’est pas nécessaire d’utiliser ce mot clé devant le corps de la fonction.

Dès qu’une fonction est déclarée virtual, elle reste virtuelle à tous les niveaux dela hiérarchie d’héritage, même si elle n’est pas déclarée virtual lorsqu’elle estremplacée par une autre classe.Ceci dit, il est préférable de déclarer explicitement ces fonctions comme virtual àchaque niveau hiérarchique, pour favoriser la clarté du programme.

Page 36: Chapitre VI

Chapitre VI - Polymorphisme 36

Déclaration d’une fonction Déclaration d’une fonction membre polymorphe (virtuelle)membre polymorphe (virtuelle)

Exemple précédent:

class materiel{

protected:char Reference[20+1];char Marque[20+1];

public:Materiel(char *r, char *m);virtual void Affiche();

};

class Micro : public Materiel{

protected:char Processeur[20+1];int Disque;

public:Micro(char *r, char *m,

char *p, int d);virtual void Affiche();

};

Page 37: Chapitre VI

37

Déclaration d’une fonction Déclaration d’une fonction membre polymorphe (virtuelle)membre polymorphe (virtuelle)

Ref : X01 Marque : XXRef : X16 Marque : PH Processeur : DX4-100 Disque : 200

Une fonction polymorphe est une méthode qui est appelée en fonction du typed’objet et non pas en fonction du type de pointeur utilisé.

Nous n’avons pas besoin d’utiliser une instruction switch quiexécuterait une action appropriée au type de chaque objet traité.

Grâce au polymorphisme, 2 classes peuvent réagir différemment au mêmeappel de méthode.

On peut donc constituer des hiérarchies de classes qui partagent une tramecommune et qui se différencient les unes des autres.

Page 38: Chapitre VI

Chapitre VI - Polymorphisme 38

Déclaration d’une fonction Déclaration d’une fonction membre polymorphe (virtuelle)membre polymorphe (virtuelle)

Lorsque vous appelez une fonction virtuelle pour un objet, le C++ cherche cette méthode dans la classe correspondante.

Si cette fonction n’existe pas dans la classe concernée, le C++ remonte la hiérarchiedes classes jusqu’à ce qu’il trouve la fonction appelée.

La résolution des appels de fonctions virtuelles a lieu à l’exécution des programmescar ce n’est qu’à cet instant, que le type d’objet pointé sera connu par C++.

Fonctions non virtuelles : le choix de la méthode se fait au moment de lacompilation du programme.

Toutefois, lorsque nous appelons une fonction virtual en référençant un objetspécifique par son nom, comme dans objet.Affiche(), la référence est résoluelors de la compilation et la fonction virtual appelée est celle définie pour laclasse de cet objet particulier ou héritée par elle.

Page 39: Chapitre VI

Chapitre VI - Polymorphisme 39

Exemple : Ajout d ’une nouvelle Exemple : Ajout d ’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Liste_simple

Polygone_2D

Polygone_2D_convexe

« hérite de »

Triangle_2D

« hérite de »

Ajout de la fonctionPoint_interieur_Polygone_2D

Page 40: Chapitre VI

Chapitre VI - Polymorphisme 40

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Point intérieur

Polygone quelconque Polygone Convexe

Page 41: Chapitre VI

Chapitre VI - Polymorphisme 41

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Polygone_2D.h

virtual void Point_interieur_Polygone_2D(float *x, float *y);

/* Permet de calculer un point intérieur au polygone 2D quelconque.

Pré - Le polygone 2D a déjà été créé et le nombre de sommetsest >= 3.

Post - Retourne en paramètres les coordonnées réelles d'un pointintérieur au polygone 2D. */

Page 42: Chapitre VI

Chapitre VI - Polymorphisme 42

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Polygone_2D_convexe.h

virtual void Point_interieur_Polygone_2D(float *x, float *y);

/* Permet de calculer un point intérieur au polygone 2D convexe.

Pré - Le polygone 2D a déjà été créé et le nombre de sommetsest >= 3.

Post - Retourne en paramètres les coordonnées réelles d'un pointintérieur au polygone 2D. */

Page 43: Chapitre VI

Chapitre VI - Polymorphisme 43

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Triangle_2D.h

Aucun ajout.

Fichier Polygone_2D.cpp

void Polygone_2D::Point_interieur_Polygone_2D(float *x, float *y){/***************************************************** *//* à développer *//******************************************************/

*x = 0.0; *y = 0.0;}

Page 44: Chapitre VI

Chapitre VI - Polymorphisme 44

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Polygone_2D_convexe.cpp

void Polygone_2D_convexe::Point_interieur_Polygone_2D(float *x, float *y)

{float u, v;Point_visible_Polygone_2D_convexe(&u, &v);*x = u; *y = v;

}Fichier Triangle_2D.cpp

Aucun ajout.

Page 45: Chapitre VI

Chapitre VI - Polymorphisme 45

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Application.cpp

#include <iostream.h>#include "Triangle_2D.h"void main(){

float a, b;Polygone_2D P;Triangle_2D Q;

P.Ajouter_sommet(1, 1); Q.Ajouter_sommet(1, 1);P.Ajouter_sommet(1, 3); Q.Ajouter_sommet(1, 3);P.Ajouter_sommet(4, 3); Q.Ajouter_sommet(4, 3);

Page 46: Chapitre VI

Chapitre VI - Polymorphisme 46

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Application.cpp(suite)

if (Q.Acces_statut() == triangle) cout << " Ceci est un triangle.";

cout << "Nombre de sommets : " << Q.Nombre_de_sommets();cout << "Aire du triangle 2D : " << Q.Aire_Polygone_2D();Q.Point_visible_Polygone_2D_convexe(&a, &b);cout << "Point visible : " << a << " , " << b;Q.Point_interieur_Polygone_2D(&a, &b);cout << "Point interieur de Q: " << a << " , " << b;P.Point_interieur_Polygone_2D(&a, &b);cout << "Point interieur de P: " << a << " , " << b;

Page 47: Chapitre VI

Chapitre VI - Polymorphisme 47

Exemple : Ajout d’une nouvelle Exemple : Ajout d’une nouvelle fonction à la classe Polygone_2Dfonction à la classe Polygone_2D

Fichier Application.cpp (suite)

P.Detruire_Polygone_2D(); Q.Detruire_Polygone_2D();cout << "Nombre de sommets de Q: " << Q.Nombre_de_sommets()

<< "Nombre de sommets de P: " << P.Nombre_de_sommets();}

FIN

Page 48: Chapitre VI

Chapitre VI - Polymorphisme 48

Polymorphisme, pour quoi faire?Polymorphisme, pour quoi faire?

Dès que vous souhaitez modifier le comportement d’une classe de baseou la spécialiser.3 raisons pour redéfinir une fonction virtuelle dans une classe dérivée:

pour la substituer au traitement standard

préciser dans cette fonction le nouveau traitement.

pour compléter le traitement standard

appeler la méthode de la classe de base dans votre fonction

ajouter d’autres traitements.

pour annuler le traitement standard

définir la fonction virtuelle dans votre classe

ne rien insérer à l’intérieur du corps de la méthode.

Page 49: Chapitre VI

Chapitre VI - Polymorphisme 49

Polymorphisme, pour quoi faire?Polymorphisme, pour quoi faire?

Rien ne nous oblige à redéfinir une fonction virtuelle dans une classe dérivéesi le traitement réalisé par la classe de base vous convient.

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

Nous avons appelé jusqu’à maintenant les fonctions polymorphes directement endésignant l’objet traité.

Qu’arrive-t-il lorsque cette fonction polymorphe est utilisée par une autre méthodede la classe ?

Page 50: Chapitre VI

Chapitre VI - Polymorphisme 50

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

Tiré de [Dupin, 99; pp. 258-260]

#include <iostream.h>#include <string.h>

class materiel{

protected:char Reference[20+1];char Marque[20+1];

public:Materiel(char *r, char *m);virtual void Affiche();void AfficheTitre();

};

class Micro : public Materiel{

protected:char Processeur[20+1];int Disque;

public:Micro(char *r, char *m,

char *p, int d);virtual void Affiche();

};

Ajout d ’une nouvelle méthode

Page 51: Chapitre VI

Chapitre VI - Polymorphisme 51

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

Materiel::Materiel(char *r, char *m){

strcpy(Reference, r);strcpy(Marque, m);

}void Materiel::Affiche(){

cout << "Ref : "   << Reference;cout << "Marque : "   << Marque;cout <<   "\n";

}

void Materiel::AfficheTitre(){

cout <<   "DEBUT\n ";Affiche();cout <<  "FIN\n";

}

Micro :: Micro(char *r, char *m,char *p, int d)

:Materiel(r,m){

strcpy(Processeur, p);Disque = d;

}

Page 52: Chapitre VI

Chapitre VI - Polymorphisme 52

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

void Micro::Affiche(){

cout << "Ref : "   << Reference; cout << "Marque : "   << Marque; cout << "Proc : "   << Processeur; cout << "Disque : "   << Disque; cout <<   "\n";

}

void main(){

Micro *pMic = NULL;pMic = new Micro("X16",  "PH",   "DX4-100", 200);pMic -> AfficheTitre();delete pMic;

}

DEBUTRef : X16 Marque : PH Processeur : DX4-100 Disque : 200FIN

Page 53: Chapitre VI

Chapitre VI - Polymorphisme 53

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

L’exécution de la fonction AfficheTitre() entraîne l’appel à une fonctionAffiche(), laquelle?

C++ exécutera la méthode virtuelle en fonction du type d’objet, quel que soitl’endroit d’où provient cet appel i.e. la fonction Affiche() de Micro.

Avantage On peut modifier un traitement standard sans y toucher.

Les fonctions virtuelles ne peuvent pas être utilisées dans le corps des constructeurs.

Un constructeur appellera toujours la fonction définie dans sa classe ou àdéfaut celle d’une classe de base, mais jamais la fonction virtuelle d’uneclasse dérivée.

Note : Les constructeurs ne peuvent pas être virtuels.

Page 54: Chapitre VI

Chapitre VI - Polymorphisme 54

Généralisation de l’appel des Généralisation de l’appel des fonctions polymorphesfonctions polymorphes

Pourquoi? Le corps du constructeur de la classe de base s’exécute avant celui de laclasse dérivée.Ainsi, au moment de l’exécution du constructeur de la classe de base,l’initialisation à réaliser par le constructeur de la classe dérivée n’est paseffectuée.

Un destructeur ne peut pas appeler une fonction virtuelle d’une classe dérivée.

Pourquoi? Le destructeur de la classe de base est appelé après celui de la classedérivée.

Page 55: Chapitre VI

Chapitre VI - Polymorphisme 55

Appel de la fonction membre Appel de la fonction membre d’une classe de based’une classe de base

Au lieu de substituer au traitement standard, dans certains cas, il est préférable decompléter le traitement de la classe de base plutôt que de le remplacer.

Il s’agit d’appeler la fonction virtuelle d’origine à partir de la nouvelle méthode.

Ex. La fonction Affiche() de Micro utilise la fonction Affiche() de la classe Materiel.

Réutilisationde

code

void Micro::Affiche(){

Materiel::Affiche();cout <<   " Processeur : "   << Processeur;cout << "  Disque : "   << Disque;cout << "\n ";

} Appel de la fonctionde la classe de base

Page 56: Chapitre VI

Chapitre VI - Polymorphisme 56

Appel de la fonction membre Appel de la fonction membre d’une classe de based’une classe de base

Avantage Si la fonction Affiche() de Materiel est modifiée, les classes dérivées enbénéficieront.

Le nom complet de la fonction Affiche() de la classe Materiel doit être utilisépour éviter un appel récursif.

Page 57: Chapitre VI

Chapitre VI - Polymorphisme 57

Polymorphisme et définition Polymorphisme et définition d’un destructeurd’un destructeur

Si un objet est détruit explicitement par l’application de l’opérateur delete sur unpointeur de classe de base vers l’objet, la fonction de destructeur de classe de baseest appelée sur l’objet, indépendamment du type d’objet pointé par le pointeur dela classe de base.

Lorsque vous définissez un destructeur de la classe de base, vous devez donc ledéclarer en tant que fonction virtuelle.

Autrement, la mémoire ne sera pas complètement libérée.

Cela rend automatiquement virtuels les destructeurs de toutes les classes dérivées.

Dès lors, si un objet de la hiérarchie est détruit explicitement avec delete sur unpointeur de classe de base vers l’objet de classe dérivée, le destructeur de la classeappropriée est appelé.

Page 58: Chapitre VI

58

Polymorphisme et définition Polymorphisme et définition d’un destructeurd’un destructeur

Si la classe Polygone_2D_convexe contenait un destructeur, et qu’il n’est pas virtuel,C++ utilisera le type de pointeur et non pas le type d’objet et détruira seulement lapartie Polygone_2D de cet objet.

Rappel

Lorsqu’un objet de la classe dérivée est détruit, la partie classe de base de cet objetest également détruite, car le destructeur de classe de base s’exécute automatiquementaprès le destructeur de classe dérivée.

En pratique

Si une classe possède des fonctions virtuelles, fournissez-lui un destructeur virtuelmême si ce dernier n’est pas obligatoire pour cette classe. Les classes dérivées decette classe peuvent en effet contenir des destructeurs qui doivent être appeléscorrectement.

Ex. : Polygone_2D * P;P = new Polygone_2D_convexe;delete P;

Page 59: Chapitre VI

Chapitre VI - Polymorphisme 59

Classes abstraites et fonctions Classes abstraites et fonctions virtuelles puresvirtuelles pures

Une classe abstraite est une classe qui ne peut être instanciée, i.e. on ne peut pascréer d’objet directement à partir de cette classe, mais on le peut grâce au mécanismede l’héritage.

Une classe devient abstraite si elle possède au moins une fonction virtuelle pure.

La plupart du temps, lorsqu’on crée une classe, c’est dans le but de créer desinstances de cette classe. Ce n’est pas toujours le cas …

On peut se servir d’une telle classe pour regrouper des concepts sous une classethéorique.On peut aussi vouloir imposer une interface générale que toutes les classes héritièresdevront implanter.

Même si nous ne pouvons pas instancier des objets de classes de base abstraites, nouspouvons quand même déclarer des pointeurs et des références vers ces classes pourmanipuler des objets de classes dérivées de façon polymorphique lorsque ces objetssont instanciés à partir de classes concrètes (non abstraites).

Page 60: Chapitre VI

Chapitre VI - Polymorphisme 60

Classes abstraites et fonctions Classes abstraites et fonctions virtuelles puresvirtuelles pures

Avantage: Oblige les classes dérivées à redéfinir des fonctions membres de laclasse de base sous peine de devenir elles-mêmes abstraites.

De cette manière, les classes dérivées n’utiliseront jamais laméthode de la classe de base.

2 incidences:(i) Une classe qui contient la définition d’une fonction virtuelle pure devient une

classe abstraite.

(ii) La redéfinition des fonctions virtuelles pures est obligatoire dans toutes lesclasses dérivées.Autrement, les classes dérivées deviennent également abstraites.

Une fonction virtuelle pure est une fonction virtuelle pour laquelle le prototype estsuivi de l’expression = 0.

Ex.: virtual void Affiche() = 0;

Page 61: Chapitre VI

Chapitre VI - Polymorphisme 61

Classes abstraites et fonctions Classes abstraites et fonctions virtuelles puresvirtuelles pures

Liste_simple

Polygone_2D

Polygone_2D_convexe

« hérite de »

Triangle_2D

« hérite de »

Conique

Figure_geometrique_2D

enum type_de_figure{polygone, conique};class Figure_geometrique_2D //classe abstraite{protected: type_de_figure Figure;public:

virtual type_de_figureAcces_type_figure()=0;

};à redéfinir dans les

classes dérivées

« hérite de » « hérite de »

Page 62: Chapitre VI

62

Exemple de classes abstraitesExemple de classes abstraites

#include "Point_3D.h"enum type_de_courbe_parametrique {constante_3D, segment_3D,

courbe_de_Bezier, courbe_parametrique_de_degre_3, courbe_parametrique_quelconque};

/* Cette classe abstraite permet de définir et de manipuler des courbesparamétriques dans [0, 1] : courbe constante, segment 3D, courbe deBézier et courbe de degré 3. Elle permet aussi de définir des courbesparamétriques quelconques (des courbes qui ne sont pas définies dansPGC++ et pour lesquelles, il n'est pas pertinent de le faire) dans[0, 1] en construisant des classes dérivées de cette classe abstraite.

Cette classe renferme des fonctions virtuelles pures lesquelles devront êtreredéfinies obligatoirement dans les classes dérivées. */

Page 63: Chapitre VI

63

Exemple de classes abstraitesExemple de classes abstraites

class Courbe_parametrique {

protected :type_de_courbe_parametrique Courbe;

public :Courbe_parametrique(type_de_courbe_parametrique T)

{ Courbe = T;}/* Permet de créer une courbe paramétrique d'un certain type.

Pré - Nil.Post - Une courbe de type T est créée. */

virtual type_de_courbe_parametriqueAcces_type_de_courbe_parametrique() = 0;

/* Permet d'identifier le type de courbe paramétrique qui a été définie.Pré - La courbe doit avoir été définie.Post - Retourne le type de courbe paramétrique créée.*/

Page 64: Chapitre VI

64

Exemple de classes abstraitesExemple de classes abstraites

virtual Point_3D & operator ()(float u) = 0;/* Permet d'évaluer la courbe courante à u dans l'intervalle [0, 1].

Pré - La courbe courante est créée.Post - Retourne le point sur la courbe à u. */

virtual Vecteur_3D & Tangente(float u) = 0;/* Permet de calculer la tangente unitaire à la courbe à u.

Pré - La courbe courante est créée.Post - Retourne la tangente unitaire à la courbe à u.*/

virtual float Longueur(float u1, float u2) = 0;/* Permet de calculer la longueur de la courbe dans l'intervalle

[u1, u2].Pré - La courbe courante est créée. 0 <= u1, u2 <= 1.Post - Retourne la longueur de la courbe dans l'intervalle

[u1, u2]. */

Page 65: Chapitre VI

Chapitre VI - Polymorphisme 65

Exemple de classes abstraitesExemple de classes abstraites

virtual bool Courbe_plane() = 0;

/* Permet de déterminer si une courbe 3D est plane ou non.

Pré - La courbe courante est créée.

Post - Retourne true si la courbe est plane. False autrement.La courbe n'est pas considérée plane lorsqu'il s'agitd'un point ou d'un segment de droite. */

};

Page 66: Chapitre VI

66

Exemple de classes abstraitesExemple de classes abstraites

#include "Courbe_parametrique.h"class Segment_3D : public Courbe_parametrique{

protected :Point_3D S1; Point_3D S2;

public :Segment_3D(Point_3D & P1, Point_3D & P2);/* Permet de créer un segment de droite 3D.

Pré - Nil.Post - Un segment de droite 3D d'extrémités P1 et P2 est

créée. */type_de_courbe_parametrique Acces_type_de_courbe_parametrique();/* Permet d'identifier le type de courbe parametrique définie.

Pré - La courbe doit avoir été définie.Post - Retourne le type de courbe parametrique créée,

soit un segment de droite. */

Page 67: Chapitre VI

67

Exemple de classes abstraitesExemple de classes abstraites

void Acces_definition_segment_3D(Point_3D * P1, Point_3D * P2);/* Donne accès à la définition du segment 3D courant.

Pré - La courbe doit avoir été définie.Post - Retourne les extrémités du segment 3D courant. */

Segment_3D & operator = (Segment_3D & S);/* Permet d'affecter S à la courbe courante.

Pré - S est créée. Le segment courant est créé.Post - La courbe courante renferme maintenant la définition de S.*/

Point_3D & operator[](int i);/* Permet d'accéder ou de modifier l'extrémité i (= 1 ou 2) du segment

de droite courant.Pré - Le segment de droite courant est créé et initialisé.Post - Accède ou modifie l'extrémité i (= 1 ou 2) du segment de

droite courant. */

Page 68: Chapitre VI

Chapitre VI - Polymorphisme 68

Exemple de classes abstraitesExemple de classes abstraites

Point_3D & operator ()(float u);

/* Permet d'évaluer la courbe courante à u dans l'intervalle [0, 1].Pré - La courbe courante est créée.Post - Retourne le point sur la courbe à u. */

Vecteur_3D & Tangente(float u);

/* Permet de calculer la tangente au segment de droite à u.Pré - La courbe courante est créée.Post - Retourne le vecteur S2 - S1. */

Page 69: Chapitre VI

Chapitre VI - Polymorphisme 69

Exemple de classes abstraitesExemple de classes abstraites

float Longueur(float u1, float u2);

/* Permet de calculer la longueur du segment de droite dansl'intervalle [u1, u2].Pré - Le segment de droite est créé. 0 <= u1, u2 <= 1.Post - Retourne la longueur du segment de droite dans

l'intervalle [u1, u2]. */

bool Courbe_plane();

/* Pré - La courbe courante est créée.Post - Retourne false car la courbe n'est pas considérée plane

lorsqu’il s'agit d'un point ou d'un segment de droite. */};

Segment_3D.cpp

Page 70: Chapitre VI

70

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

// Exemple tiré du livre "Comment programmer en C++, Deitel et Deitel, // Eyrolles, pp. 569-579.#include <iostream.h>#include <string.h>#include <iomanip.h>class Employe // Classe de base abstraite{

private: char * prenom;char * nomFamille;

public: Employe(const char * prenom, const char * nom);~Employe();const char * lecturePrenom() const;const char * lectureNomFamille() const;virtual double gains() const = 0; // Fonction virtuelle purevirtual void affichage() const; // Fonction virtuelle

};

Page 71: Chapitre VI

Chapitre VI - Polymorphisme 71

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

Employe::Employe(const char * premier, const char * dernier){

prenom = new char[strlen(premier) + 1];strcpy(prenom, premier);

nomFamille = new char[strlen(dernier) + 1];strcpy(nomFamille, dernier);

}

Employe::~Employe(){

delete [] prenom;delete [] nomFamille;

}

Page 72: Chapitre VI

Chapitre VI - Polymorphisme 72

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

// Renvoie un pointeur vers le prénom. Un renvoi de type const empêche// l'appelant de modifier les données private. L'appelant doit copier// la chaîne renvoyée avant que le destructeur ne supprime la mémoire// dynamique pour empêcher la formation d'un pointeur non défini.const char * Employe::lecturePrenom() const{ return prenom;}

// Renvoie un pointeur vers le nom de famille. Un renvoi de type const// empêche l'appelant de modifier les données private. L'appelant doit// copier la chaîne renvoyée avant que le destructeur ne supprime la// mémoire dynamique pour empêcher la formation d'un pointeur non défini.const char * Employe::lectureNomFamille() const{ return nomFamille;}

Page 73: Chapitre VI

Chapitre VI - Polymorphisme 73

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

void Employe::affichage() const{

cout << prenom << " " << nomFamille;}

//------------------------ Fin de la classe Employe -------------------

Page 74: Chapitre VI

Chapitre VI - Polymorphisme 74

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

class Patron: public Employe // Classe dérivée de la classe Employe{

private:double salaireHebdo;

public:Patron(const char * prenom, const char * nom,

double salaireHebdo = 0.0);

void ajusterSalaireHebdo(double salaireHebdo);// Ajuste le salaire du patron.

virtual double gains() const; // Lit la paie du patron.

virtual void affichage() const; // Affiche le nom du patron.};

Page 75: Chapitre VI

75

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

Patron::Patron(const char * premier, const char * dernier, double salaire) : Employe(premier, dernier)

{ ajusterSalaireHebdo(salaire);}void Patron::ajusterSalaireHebdo(double salaire){ salaireHebdo = salaire;}double Patron::gains() const{ return salaireHebdo;}void Patron::affichage() const{ cout << "\n Patron: ";

Employe::affichage();}//------------------------ Fin de la classe Patron -------------------

Page 76: Chapitre VI

76

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

class EmployeCommission: public Employe // Classe dérivée de la classe Employe{private:

double salaire; // salaire hebdomadaire de basedouble commission; // montant par article venduint quantite; // total d'articles vendus pour la semaine

public:EmployeCommission(const char * prenom, const char * nom,

double salaire = 0.0, double commission = 0.0, int quantite = 0);

void ajusterSalaire(double salaire); // Ajuste le salaire.void ajusterCommission(double commission); // Ajuste la commission.void ajusterQuantite(int quantite); // Ajuste le total d'articles vendus.virtual double gains() const; // Lit la paie de l'employé à commission.virtual void affichage() const; // Affiche le nom de l'employé à commission.

};

Page 77: Chapitre VI

Chapitre VI - Polymorphisme 77

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

EmployeCommission::EmployeCommission(const char * premier, const char * dernier,double s, double c, int q)

: Employe(premier, dernier){

ajusterSalaire(s);ajusterCommission(c);ajusterQuantite(q);

}void EmployeCommission::ajusterSalaire(double s){

salaire = s;}void EmployeCommission::ajusterCommission(double c){

commission = c;}

Page 78: Chapitre VI

Chapitre VI - Polymorphisme 78

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

void EmployeCommission::ajusterQuantite(int q){

quantite = q;}double EmployeCommission::gains() const{

return salaire + commission * quantite;}void EmployeCommission::affichage() const{

cout << "\n Employe a commission: ";Employe::affichage();

}//--------------------- Fin de la classe EmployeCommission ----------------

Page 79: Chapitre VI

Chapitre VI - Polymorphisme 79

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

class EmployePiece: public Employe // Classe dérivée de la classe Employe{private:

double tauxParPiece; // taux pour chaque pièce produiteint quantite; // quantité produite pour la semaine

public:EmployePiece(const char * prenom, const char * nom,

double tauxParPiece = 0.0, int quantite = 0);

void ajusterPaie(double tauxParPiece); // Ajuste le taux par pièce.void ajusterQuantite(int quantite); // Ajuste la qté produite pour la semaine.

virtual double gains() const; // Lit la paie de l'employé à la pièce.virtual void affichage() const; // Affiche le nom de l'employé à la pièce.

};

Page 80: Chapitre VI

Chapitre VI - Polymorphisme 80

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

EmployePiece::EmployePiece(const char * premier, const char * dernier, double w, int q)

: Employe(premier, dernier){

ajusterPaie(w);ajusterQuantite(q);

}void EmployePiece::ajusterPaie(double w){

tauxParPiece = w;}void EmployePiece::ajusterQuantite(int q){

quantite = q;}

Page 81: Chapitre VI

Chapitre VI - Polymorphisme 81

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

double EmployePiece::gains() const{

return tauxParPiece * quantite;}

void EmployePiece::affichage() const{

cout << "\nEmploye paye a la piece: ";Employe::affichage();

}

//------------------------ Fin de la classe EmployePiece -------------------

Page 82: Chapitre VI

82

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

class EmployeHoraire: public Employe // Classe dérivée de la classe Employe{

private:double tauxHoraire; // taux horairedouble heures; // heures travaillées pour la semaine

public:EmployeHoraire(const char * prenom, const char * nom,

double tauxHoraire = 0.0, double heures = 0);

void ajusterPaie(double tauxHoraire); // Ajuste le taux horaire.void ajusterHeures(double heures);

// Ajuste les heures travaillées pour la semaine.

virtual double gains() const; // Lit la paie de l'employé à l'heure.virtual void affichage() const; // Affiche le nom de l'employé à l'heure

};

Page 83: Chapitre VI

Chapitre VI - Polymorphisme 83

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

EmployeHoraire::EmployeHoraire(const char * premier, const char * dernier,double w, double h)

: Employe(premier, dernier){

ajusterPaie(w);ajusterHeures(h);

}void EmployeHoraire::ajusterPaie(double w){

tauxHoraire = w;}void EmployeHoraire::ajusterHeures(double h){

heures = h;}

Page 84: Chapitre VI

Chapitre VI - Polymorphisme 84

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

double EmployeHoraire::gains() const{

if (heures <= 40) return tauxHoraire * heures;else return 40 * tauxHoraire + (heures - 40) * tauxHoraire * 1.5;

}

void EmployeHoraire::affichage() const{

cout << "\n Employe horaire: ";Employe::affichage();

}

//------------------------ Fin de la classe EmployeHoraire -------------------

Page 85: Chapitre VI

85

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

void virtuelViaPointeur( const Employe * E);void virtuelViaReference(const Employe & E);void main(){

Patron b("Jean", "Soucy", 800.00);b.affichage();cout << " a gagne $" << b.gains();virtuelViaPointeur( &b );virtuelViaReference( b );

EmployeCommission c("Lise", "Jobin", 200.00, 3.0, 150);c.affichage();cout << " a gagne $" << c.gains();virtuelViaPointeur( &c );virtuelViaReference( c );

Page 86: Chapitre VI

86

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

EmployePiece p("Benoit", "Cyr", 2.5, 200);p.affichage();cout << " a gagne $" << p.gains();virtuelViaPointeur( &p );virtuelViaReference( p );

EmployeHoraire h("Karine", "Roy", 13.75, 40);h.affichage();cout << " a gagne $" << h.gains();virtuelViaPointeur( &h );virtuelViaReference( h );cout << endl;

}

Page 87: Chapitre VI

87

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

void virtuelViaPointeur( const Employe * classeBasePtr ){

classeBasePtr -> affichage();cout << " a gagne $" << classeBasePtr -> gains();

}

void virtuelViaReference( const Employe & classeBaseRef ){

classeBaseRef.affichage();cout << " a gagne $" << classeBaseRef.gains();

}

Page 88: Chapitre VI

88

Système de paie utilisant le polymorphismeSystème de paie utilisant le polymorphisme

Patron: Jean Soucy a gagne $800.00 Patron: Jean Soucy a gagne $800.00 Patron: Jean Soucy a gagne $800.00 Employe a commission: Lise Jobin a gagne $650.00 Employe a commission: Lise Jobin a gagne $650.00 Employe a commission: Lise Jobin a gagne $650.00Employe paye a la piece: Benoit Cyr a gagne $500.00Employe paye a la piece: Benoit Cyr a gagne $500.00Employe paye a la piece: Benoit Cyr a gagne $500.00 Employé horaire: Karine Roy a gagné $550.00 Employé horaire: Karine Roy a gagné $550.00 Employé horaire: Karine Roy a gagné $550.00

FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN FIN