SlideShare une entreprise Scribd logo
1  sur  48
Télécharger pour lire hors ligne
Programmation Orientée Objet en C++
        12ème Partie: Polymorphisme



               Fabio Hernandez
             Fabio.Hernandez@in2p3.fr
Vue d'Ensemble
   Notions de base
   Types, variables, opérateurs
   Contrôle d'exécution
   Fonctions
   Mémoire dynamique
   Qualité du logiciel
   Evolution du modèle objet
   Objets et classes
   Fonctions membres
   Classes génériques
   Héritage
   Polymorphisme
   Héritage multiple
   Entrée/sortie


POO en C++: Polymorphisme         401        © 1997-2003 Fabio HERNANDEZ
Table des Matières

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme          402           © 1997-2003 Fabio HERNANDEZ
Motivation

   Le mécanisme d'héritage permet aux sous-classes d'utiliser
   l'implémentation des méthodes de la classe de base
   Nous allons étudier un mécanisme étroitement lié à l'héritage
   appelé polymorphisme
   Polymorphisme signifie la possibilité d ’un objet de prendre
   plusieurs formes
   Dans le contexte du modèle objet cela signifie qu'une "entité"
   du langage peut être attachée en temps d'exécution à des
   objets de classes différentes
   Dans le cas de C++, cette "entité" ne peut être qu'un pointeur
   ou une référence


POO en C++: Polymorphisme      403                © 1997-2003 Fabio HERNANDEZ
Motivation (suite)

   Ce mécanisme permet de manipuler d'une façon uniforme un
   ensemble d'objets appartenant à une même hiérarchie de
   classes




POO en C++: Polymorphisme          404           © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            405            © 1997-2003 Fabio HERNANDEZ
Affectation Polymorphe

                                       Figure



              OpenFigure                               ClosedFigure



     Segment                Polyline              Polygon             Ellipse



                                Triangle         Rectangle    ...       Circle


                                                  Square

POO en C++: Polymorphisme                  406               © 1997-2003 Fabio HERNANDEZ
Affectation Polymorphe (suite)

   Si nous déclarons les objets
          Polygon aPolygon;
          Triangle aTriangle;
          Square aSquare;
   Nous pouvons déclarer le pointeur
          Polygon* polygonPtr;
   Et les affectations suivantes sont valides
          polygonPtr = &aTriangle; // aTriangle is-a Polygon
          polygonPtr = &aSquare;   // aSquare is-a Polygon
          polygonPtr = new Rectangle; // a Rectangle is-a Polygon
   Le mécanisme d'héritage nous permet de traiter une instance
   de la classe Triangle ou Square comme une instance de
   Polygon
POO en C++: Polymorphisme         407            © 1997-2003 Fabio HERNANDEZ
Affectation Polymorphe (suite)

   Notez qu'il n'y a aucune transformation des objets aTriangle
   et aSquare
         une fois crée un objet ne change pas son type
   Les pointeurs et références peuvent être "attachés" à des
   objets de types différents descendants d'un ancêtre commun
   Pour le passage de paramètres nous pouvons utiliser le même
   principe
         soit la fonction
          void inspect(const Polygon& aPolygon)
          {
               // Do something with the parameter object
          }


POO en C++: Polymorphisme              408               © 1997-2003 Fabio HERNANDEZ
Affectation Polymorphe (suite)

   Nous pouvons appeler cette fonction avec comme argument un
   objet descendant de Polygon

          Square aSquare;
          Triangle aTriangle;

          inspect(aSquare);     // OK: aSquare is a Polygon
          inspect(aTriangle);   // OK: aTriangle is a Polygon

          Circle aCircle;
          inspect(aCircle);   // COMPILATION ERROR: aCircle is
                              // not a kind of Polygon



POO en C++: Polymorphisme        409              © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            410            © 1997-2003 Fabio HERNANDEZ
Structures de Données Polymorphes

   Soit le tableau
           Polygon* polygonArray[4];
           polygonArray[0] = new Rectangle;
           polygonArray[1] = new Square;
           polygonArray[2] = new Triangle;
           polygonArray[3] = new Polygon;
   Nous pouvons le visualiser comme

     0
     1
     2
     3
          polygonArray


POO en C++: Polymorphisme        411          © 1997-2003 Fabio HERNANDEZ
Structures de Données Polymorphes (suite)

   Une structure polymorphe est une structure qui contient des
   objets de types différents descendants d'une classe commune
   Tous les conteneurs que nous avons étudiés peuvent être des
   structures polymorphes (List, Queue, Set, Bag, Stack, ...)
   L'intérêt des conteneurs polymorphes c'est qu'ils offrent la
   possibilité de traiter d'une façon uniforme tous les objets
   contenus
   Supposons par exemple que nous voulons calculer la somme des
   périmètres des polygones contenus dans notre tableau
   Une façon naturelle serait de faire une boucle pour parcourir
   chacune des positions du tableau en calculant le périmètre du
   polygone correspondant et d'en faire l'addition

POO en C++: Polymorphisme      412              © 1997-2003 Fabio HERNANDEZ
Structures de Données Polymorphes (suite)

   Calcul du périmètre (suite)
          float total = 0.0;
          for (int pos=0; pos < MaxPositions; pos++) {
             total += Perimeter of polygonArray[pos];
          }
   Quelle méthode faudrait-il appeler sur l'objet pointé par
   polygonArray[pos] pour obtenir son périmètre?
   Regardons la définition de la classe Polygon




POO en C++: Polymorphisme        413              © 1997-2003 Fabio HERNANDEZ
Classe Polygon
          #include "Point.h"
          #include "List.h"

          class Polygon {
          public:
             // Constructors/Destructor
             Polygon();
             ~Polygon();

                // Modifiers
                void translate(float horizontal, float vertical);
                void rotate(float angle);
                ...


POO en C++: Polymorphisme           414             © 1997-2003 Fabio HERNANDEZ
Classe Polygon (suite)
                // Selectors
                float perimeter() const;
                float area() const;
                ...

          private:
             // Data members
             List<Point> vertexList_;
          };




POO en C++: Polymorphisme             415            © 1997-2003 Fabio HERNANDEZ
Classe Polygon (suite)

   L'implémentation de la fonction membre Polygon::perimeter
   pourrait être
          float Polygon::perimeter() const
          {
             int numVertices = vertexList_.length();
             float result = 0.0;
             for (int i=1; i < numVertices; i++) {
                const Point& previous = vertexList_.itemAt(i-1);
                const Point& current = vertexList_.itemAt(i);
                result += current.distanceTo(previous);
             }
             const Point& first = vertexList_.first();
             const Point& last = vertexList_.last();
             return result + first.distanceTo(last);
          }

POO en C++: Polymorphisme             416            © 1997-2003 Fabio HERNANDEZ
Classe Rectangle
          #include "Point.h"
          #include "Polygon.h"

          class Rectangle: public Polygon {
          public:




                                               side2
             // Constructors/Destructor
             Rectangle(const Point& origin,
                       float side1,
                       float side2);                     side1
             ~Rectangle();
                                               origin

                // Modifiers
                ...


POO en C++: Polymorphisme          417          © 1997-2003 Fabio HERNANDEZ
Classe Rectangle (suite)
                // Selectors
                float perimeter() const;
                float area() const;
                float diagonal() const;
                ...
                                                   Fonctions et
                                                données membres
          private:
                                                  spécifiques à la
             // Data members                    classe Rectangle
             float side1_;
             float side2_;
             Point origin_;
          };




POO en C++: Polymorphisme              418          © 1997-2003 Fabio HERNANDEZ
Classe Rectangle (suite)

   L'implémentation de la méthode Rectangle::perimeter est
   plus simple que Polygon::perimeter
          float Rectangle::perimeter() const
          {
             return 2*(side1_ + side2_);
          }
   Rectangle est donc une spécialisation de la classe Polygon et
   Rectangle::perimeter est une redéfinition de
   Polygon::perimeter
   De façon similaire pour la méthode Rectangle::area




POO en C++: Polymorphisme              419         © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            420            © 1997-2003 Fabio HERNANDEZ
Liaison Statique

   Static Binding
   La liaison est le mécanisme utilisé par le compilateur pour
   déterminer quelle fonction membre appeler sur un objet qui
   appartient à une hiérarchie de classes lorsqu'il y a redéfinition
   de méthodes
   Exemple
          Rectangle rect(Point(0.0, 1.0), 10.0, 15.0);
          Polygon poly;
          float perimeter;

          perimeter = rect.perimeter();
                            // Rectangle::perimeter() is called
          perimeter = poly.perimeter();
                            // Polygon::perimeter() is called
POO en C++: Polymorphisme         421              © 1997-2003 Fabio HERNANDEZ
Liaison Statique (suite)

   Exemple (suite)
           Polygon* polyPtr = &poly;
           perimeter = polyPtr->perimeter();
                             // Polygon::perimeter() is called

           Rectangle* rectPtr = &rect;
           perimeter = rectPtr->perimeter();
                             // Rectangle::perimeter() is called

           polyPtr = &rect;
           perimeter = polyPtr->perimeter();
            // Rectangle::perimeter() or Polygon::perimeter()?



POO en C++: Polymorphisme             422              © 1997-2003 Fabio HERNANDEZ
Liaison Statique (suite)

   Exemple (suite)
         La fonction membre appelée est Polygon::perimeter()
   Le principe de liaison statique établit que le type de l'objet sur
   lequel la méthode est appliquée détermine statiquement la
   méthode appelée
   Dans l'exemple précédent, le pointeur polyPtr pointe vers un
   objet de la classe Polygon; en conséquence, l'instruction
          polyPtr->perimeter()
   se traduit par une invocation à la méthode
       Polygon::perimeter()




POO en C++: Polymorphisme             423              © 1997-2003 Fabio HERNANDEZ
Liaison Statique (suite)

   De façon similaire l'instruction
          float diagonal = polyPtr->diagonal(); // ERROR
   est marquée par une erreur de compilation: polyPtr est défini
   comme un pointeur à Polygon et la méthode
   Polygon::diagonal n'est pas définie
   Par contre avec les instructions
          Rectangle* rectPtr = &rect;
          float diagonal = rectPtr->diagonal(); // OK
   on obtient le résultat souhaité
   Ce principe de liaison (binding) est appelé statique parce que le
   choix de la méthode à appeler est fait en temps de compilation


POO en C++: Polymorphisme             424              © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            425            © 1997-2003 Fabio HERNANDEZ
Liaison Dynamique

   Dans l'exemple précédant du calcul du périmètre
          float total = 0.0;
          for (int pos=0; pos < MaxPositions; pos++)
             total += polygonArray[pos]->perimeter();
   la méthode qui sera appelée pour chaque objet du tableau est
   Polygon::perimeter()
   Supposons que nous disposons d'une méthode pour connaître en
   temps d'exécution la classe d'un objet
         On pourrait écrire par exemple
             if (type of polygonArray[pos] == Rectangle)
                 // WARNING: this is pseudo-code
         pour déterminer si un objet est de type Rectangle


POO en C++: Polymorphisme          426              © 1997-2003 Fabio HERNANDEZ
Liaison Dynamique (suite)

   Une façon de résoudre ce problème et d'appeler la bonne
   méthode serait
          float total = 0.0;
          for (int pos=0; pos < MaxPositions; pos++) {
             // WARNING: this is pseudo-code
             if (type of polygonArray[pos] == Rectangle)
                total +=
                   ((Rectangle*)polygonArray[pos])->perimeter();
             else if (type of polygonArray[pos] == Triangle)
                total +=
                   ((Triangle*)polygonArray[pos])->perimeter();
             ....
          }

POO en C++: Polymorphisme              427          © 1997-2003 Fabio HERNANDEZ
Liaison Dynamique (suite)

   L'inconvénient de cette technique c'est qu'elle rend difficile
   les modifications
         Si une nouvelle sous-classe de Polygon est rajoutée ou une sous-classe
         existante est supprimée de la hiérarchie, cette boucle doit être
         modifiée
   Le modèle objet propose une technique pour résoudre ce
   problème appelée "Liaison Dynamique" (dynamic binding)
   Par opposition au principe de liaison statique, avec la liaison
   dynamique le compilateur ne peut décider en temps de
   compilation quelle méthode appeler. Cette décision est prise en
   temps d'exécution, par rapport à la classe de l'objet en
   question (Rectangle, Triangle, Polygon, ...)


POO en C++: Polymorphisme              428                  © 1997-2003 Fabio HERNANDEZ
Liaison Dynamique (suite)

   Contrairement à d'autres langages OO, C++ utilise par défaut la
   liaison statique
   Le programmeur est donc responsable d'informer le
   compilateur que pour une ou plusieurs méthodes d'une classe il
   souhaite utiliser la liaison dynamique
   Le mot clé du langage pour exprimer ce concept est virtual
   Nous devons en conséquence modifier l'interface de notre
   classe Polygon pour indiquer que la fonction membre
   Polygon::perimeter sera virtual




POO en C++: Polymorphisme              429          © 1997-2003 Fabio HERNANDEZ
Classe Polygon
          class Polygon {
          public:
             // Constructors/Destructor
             ...

                // Modifiers
                ...

                // Selectors                         Définition des
                virtual float perimeter() const;   fonctions membres
                virtual float area() const;        Perimeter et area
                ...                                comme ayant liaison
                                                       dynamique
          private:
             // Data members
             ...
          };

POO en C++: Polymorphisme          430              © 1997-2003 Fabio HERNANDEZ
Classe Polygon (suite)

   Notez que l'implémentation des fonctions
   Polygon::perimeter et Polygon:: area reste inchangée
   Les interfaces des sous-classes de Polygon (Rectangle,
   Triangle, ...) peuvent rester inchangées. Néanmoins, pour
   clarté nous allons propager la modification de l'interface de
   Polygon à toutes ses sous-classes
   Regardons le cas de la classe Rectangle




POO en C++: Polymorphisme             431            © 1997-2003 Fabio HERNANDEZ
Classe Rectangle
          class Rectangle: public Polygon {
          public:
                                                 Propagation pour
             // Constructors/Destructor
                                                   clarté de la
             ...                                  définition des
             // Modifiers                       fonctions membres
             ...                                Perimeter et area
             // Selectors                        comme virtual.
             virtual float perimeter() const;
             virtual float area() const;
                                                  Définition de la
             virtual float diagonal() const;
                                                méthode diagonal
             ...
                                                 comme virtual.
          private:                              Affecte toutes les
             // Data members
                                                  sous-classes de
             ...
                                                     Rectangle
          };

POO en C++: Polymorphisme         432           © 1997-2003 Fabio HERNANDEZ
Calcul du périmètre

   Dans l'exemple du tableau polymorphe
      0
      1
      2
      3

    l'algorithme
           float total = 0.0;
           for (int pos=0; pos < MaxPositions; pos++)
              total += polygonArray[pos]->perimeter();
    appellera Rectangle::perimeter(),
    Square::perimeter(), Triangle::perimeter() et
    Polygon::perimeter()
POO en C++: Polymorphisme           433           © 1997-2003 Fabio HERNANDEZ
Destructeur Virtuel

   Lors de la destruction d'une structure (conteneur) polymorphe
   (List, Queue, Stack, Set, Bag, Tree, ...) les objets contenus
   seront eux aussi probablement détruits
   Le destructeur de chacun des objets sera utilisé
          for (int pos=0; pos < MaxPositions; pos++)
             delete polygonArray[pos];
   Cependant, avec le destructeur nous avons le même problème
   que avec la fonction membre perimeter
         dans ce cas particulier, à cause de la liaison statique uniquement le
         destructeur Polygon::~Polygon() sera appelé
   La solution est la même que pour les autres fonctions membres
   Le destructeur de la classe de base doit être défini virtual

POO en C++: Polymorphisme               434                    © 1997-2003 Fabio HERNANDEZ
Destructeur Virtuel (suite)
          class Polygon {
          public:
             // Constructors/Destructor
             Polygon();
             virtual ~Polygon();          Le destructeur doit
                                             être déclaré
                // Modifiers                   virtual.
                ...

                // Selectors
                ...

          private:
             // Data members
             ...
          };

POO en C++: Polymorphisme          435              © 1997-2003 Fabio HERNANDEZ
Destructeur Virtuel (suite)

   De façon similaire, pour des raisons de clarté nous déclarerons
   virtual le destructeur de toutes les sous-classes de Polygon
   D'une façon générale, on doit déclarer virtual le destructeur
   de toute classe contenant au moins une fonction membre
   virtuelle




POO en C++: Polymorphisme          436           © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            437            © 1997-2003 Fabio HERNANDEZ
Méthodes Abstraites

   Supposons que nous voulons ajouter une méthode à la classe
   Polygon pour déterminer si un point (x,y) se trouve à
   l'intérieur
   Le prototype de cette méthode pourrait être
          bool Polygon::isInside(const Point& aPoint) const
   Un tel service est facilement implémenté pour certaines sous-
   classes de Polygon (Triangle, Rectangle, Square)
   L'implémentation est plus difficile pour un polygone générique
         une implémentation par défaut n'est pas souhaitable
   Il est néanmoins nécessaire que tous les polygones, c'est à dire
   toutes les sous-classes de Polygon fournissent sa propre
   implémentation de ce service

POO en C++: Polymorphisme             438                      © 1997-2003 Fabio HERNANDEZ
Méthodes Abstraites (suite)

   Une façon de faire c'est d'implémenter le service dans la
   classe de base avec une implémentation par défaut "vide"
          bool Polygon::isInside(const Point& aPoint) const
          {
             cerr << "You must implement this routine" << endl;
             return false;
          }
   Une autre façon de faire c'est de forcer chaque sous-classe à
   fournir ce service en déclarant la méthode comme abstraite
   dans la classe de base
   Une méthode abstraite est une méthode pour laquelle la classe
   de base ne fournit pas d'implémentation


POO en C++: Polymorphisme         439            © 1997-2003 Fabio HERNANDEZ
Méthodes Abstraites (suite)

   Nous pouvons définir la méthode Polygon::isInside comme
   abstraite
   Une méthode abstraite en C++ est aussi appelée virtuelle pure




POO en C++: Polymorphisme         440            © 1997-2003 Fabio HERNANDEZ
Méthodes Abstraites (suite)
          class Polygon {
          public:
             // Constructors/Destructor             Méthode Abstraite
             ...
                                                     ou virtuelle pure
                // Modifiers
                ...

                // Selectors
                virtual bool isInside(const Point& aPoint) const = 0;
                ...

          private:
             // Data members
             ...
          };

POO en C++: Polymorphisme           441             © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            442            © 1997-2003 Fabio HERNANDEZ
Classe Abstraite

   Une classe ayant au moins une méthode abstraite est appelée
   classe abstraite
   Il est impossible de créer une instance d'une classe abstraite
         Cette vérification est effectuée par le compilateur

          Polygon aPolygon;
          // ERROR: Polygon has at least one pure virtual
          // member fonction
   Les sous-classes (instanciables) de Polygon doivent fournir une
   implémentation de cette méthode




POO en C++: Polymorphisme              443                     © 1997-2003 Fabio HERNANDEZ
Classe Abstraite (suite)
          class Rectangle: public Polygon {
          public:
             // Constructors/Destructor
             ...

                // Modifiers
                ...

                // Selectors
                virtual bool isInside(const Point& aPoint) const;
                ...

          private:
             // Data members
             ...
          };

POO en C++: Polymorphisme             444              © 1997-2003 Fabio HERNANDEZ
Classe Abstraite (suite)
          bool Rectangle::isInside(const Point& aPoint) const
          {
             if ((origin_.getX() <= aPoint. getX()) &&
                 (aPoint. getX() <= (origin_. getX() + side1_)) &&
                 (origin_.getY() <= aPoint. getY()) &&
                 (aPoint. getY() <= (origin_. getY() + side2_)))
                return true;

                return false;
          }




POO en C++: Polymorphisme             445              © 1997-2003 Fabio HERNANDEZ
Contrôle d'Avancement

   Motivation
   Affectation polymorphe
   Structures de données polymorphes
   Liaison statique
   Liaison dynamique
   Méthodes abstraites
   Classes abstraites
   Résumé




POO en C++: Polymorphisme            446            © 1997-2003 Fabio HERNANDEZ
Résumé

   Le polymorphisme permet à une référence ou à un pointeur
   d'être associé en temps d'exécution à des instances de classes
   différentes
   La liaison dynamique est le mécanisme qui permet de déterminer
   en temps d'exécution l'utilisation de la redéfinition correcte
   d'une méthode
   Une méthode abstraite ou virtuelle pure est une méthode pour
   laquelle la classe de base ne fournit pas d'implémentation
   Une classe avec une ou plusieurs méthodes abstraites est elle
   aussi abstraite
   Il est impossible de créer une instance d'une classe abstraite


POO en C++: Polymorphisme     447               © 1997-2003 Fabio HERNANDEZ

Contenu connexe

Tendances

Introduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonIntroduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonAbdoulaye Dieng
 
c# programmation orientée objet (Classe & Objet)
c# programmation orientée objet (Classe & Objet)c# programmation orientée objet (Classe & Objet)
c# programmation orientée objet (Classe & Objet)Mahfoud EL HOUDAIGUI
 
Présentation python
Présentation pythonPrésentation python
Présentation pythonSarah
 
Chapitre3TableauxEnCppV2019
Chapitre3TableauxEnCppV2019Chapitre3TableauxEnCppV2019
Chapitre3TableauxEnCppV2019Aziz Darouichi
 
Chapitre5: Classes et objets
Chapitre5: Classes et objetsChapitre5: Classes et objets
Chapitre5: Classes et objetsAziz Darouichi
 
Héritage et polymorphisme- Jihen HEDHLI
Héritage et polymorphisme- Jihen HEDHLIHéritage et polymorphisme- Jihen HEDHLI
Héritage et polymorphisme- Jihen HEDHLIJihenHedhli1
 
programmation orienté objet c++
programmation orienté objet c++programmation orienté objet c++
programmation orienté objet c++coursuniv
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationECAM Brussels Engineering School
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfacesAmir Souissi
 
Chapitre 2 classe et objet
Chapitre 2   classe et objetChapitre 2   classe et objet
Chapitre 2 classe et objetAmir Souissi
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateursAziz Darouichi
 
Formation python
Formation pythonFormation python
Formation pythonj_lipaz
 
Correction de td poo n2
Correction de td poo n2Correction de td poo n2
Correction de td poo n2yassine kchiri
 
applications-reparties
applications-repartiesapplications-reparties
applications-repartiesmourad50
 

Tendances (20)

Introduction à l’orienté objet en Python
Introduction à l’orienté objet en PythonIntroduction à l’orienté objet en Python
Introduction à l’orienté objet en Python
 
c# programmation orientée objet (Classe & Objet)
c# programmation orientée objet (Classe & Objet)c# programmation orientée objet (Classe & Objet)
c# programmation orientée objet (Classe & Objet)
 
Présentation python
Présentation pythonPrésentation python
Présentation python
 
Chapitre3TableauxEnCppV2019
Chapitre3TableauxEnCppV2019Chapitre3TableauxEnCppV2019
Chapitre3TableauxEnCppV2019
 
Corrige tp java
Corrige tp javaCorrige tp java
Corrige tp java
 
Chapitre5: Classes et objets
Chapitre5: Classes et objetsChapitre5: Classes et objets
Chapitre5: Classes et objets
 
Héritage et polymorphisme- Jihen HEDHLI
Héritage et polymorphisme- Jihen HEDHLIHéritage et polymorphisme- Jihen HEDHLI
Héritage et polymorphisme- Jihen HEDHLI
 
programmation orienté objet c++
programmation orienté objet c++programmation orienté objet c++
programmation orienté objet c++
 
python
pythonpython
python
 
Support programmation orientée objet c# .net version f8
Support programmation orientée objet c#  .net version f8Support programmation orientée objet c#  .net version f8
Support programmation orientée objet c# .net version f8
 
COURS_PYTHON_22.ppt
COURS_PYTHON_22.pptCOURS_PYTHON_22.ppt
COURS_PYTHON_22.ppt
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulation
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfaces
 
Ch 01 poo
Ch 01 pooCh 01 poo
Ch 01 poo
 
Polymorphisme
PolymorphismePolymorphisme
Polymorphisme
 
Chapitre 2 classe et objet
Chapitre 2   classe et objetChapitre 2   classe et objet
Chapitre 2 classe et objet
 
Chapitre6: Surcharge des opérateurs
Chapitre6:  Surcharge des opérateursChapitre6:  Surcharge des opérateurs
Chapitre6: Surcharge des opérateurs
 
Formation python
Formation pythonFormation python
Formation python
 
Correction de td poo n2
Correction de td poo n2Correction de td poo n2
Correction de td poo n2
 
applications-reparties
applications-repartiesapplications-reparties
applications-reparties
 

En vedette

Partie 1: Notions de base — Programmation orientée objet en C++
Partie 1: Notions de base — Programmation orientée objet en C++Partie 1: Notions de base — Programmation orientée objet en C++
Partie 1: Notions de base — Programmation orientée objet en C++Fabio Hernandez
 
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++Partie 5: Mémoire Dynamique — Programmation orientée objet en C++
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++Fabio Hernandez
 
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++Fabio Hernandez
 
Partie 13: Héritage Multiple — Programmation orientée objet en C++
Partie 13: Héritage Multiple — Programmation orientée objet en C++Partie 13: Héritage Multiple — Programmation orientée objet en C++
Partie 13: Héritage Multiple — Programmation orientée objet en C++Fabio Hernandez
 
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++Partie 6: Qualité du Logiciel — Programmation orientée objet en C++
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++Fabio Hernandez
 
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++Fabio Hernandez
 
Partie 14: Entrée/Sortie — Programmation orientée objet en C++
Partie 14: Entrée/Sortie — Programmation orientée objet en C++Partie 14: Entrée/Sortie — Programmation orientée objet en C++
Partie 14: Entrée/Sortie — Programmation orientée objet en C++Fabio Hernandez
 
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++Fabio Hernandez
 
Partie 4: Fonctions - Programmation orientée objet en C++
Partie 4: Fonctions - Programmation orientée objet en C++Partie 4: Fonctions - Programmation orientée objet en C++
Partie 4: Fonctions - Programmation orientée objet en C++Fabio Hernandez
 
Partie 10: Classes Génériques — Programmation orientée objet en C++
Partie 10: Classes Génériques — Programmation orientée objet en C++Partie 10: Classes Génériques — Programmation orientée objet en C++
Partie 10: Classes Génériques — Programmation orientée objet en C++Fabio Hernandez
 

En vedette (11)

Partie 1: Notions de base — Programmation orientée objet en C++
Partie 1: Notions de base — Programmation orientée objet en C++Partie 1: Notions de base — Programmation orientée objet en C++
Partie 1: Notions de base — Programmation orientée objet en C++
 
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++Partie 5: Mémoire Dynamique — Programmation orientée objet en C++
Partie 5: Mémoire Dynamique — Programmation orientée objet en C++
 
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++
Partie 2: Types, Variables, Opérateurs — Programmation orientée objet en C++
 
Partie 13: Héritage Multiple — Programmation orientée objet en C++
Partie 13: Héritage Multiple — Programmation orientée objet en C++Partie 13: Héritage Multiple — Programmation orientée objet en C++
Partie 13: Héritage Multiple — Programmation orientée objet en C++
 
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++Partie 6: Qualité du Logiciel — Programmation orientée objet en C++
Partie 6: Qualité du Logiciel — Programmation orientée objet en C++
 
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++
Partie 3: Contrôle d'Exécution — Programmation orientée objet en C++
 
Partie 14: Entrée/Sortie — Programmation orientée objet en C++
Partie 14: Entrée/Sortie — Programmation orientée objet en C++Partie 14: Entrée/Sortie — Programmation orientée objet en C++
Partie 14: Entrée/Sortie — Programmation orientée objet en C++
 
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++
Partie 7: Evolution du Modèle Objet — Programmation orientée objet en C++
 
Partie 4: Fonctions - Programmation orientée objet en C++
Partie 4: Fonctions - Programmation orientée objet en C++Partie 4: Fonctions - Programmation orientée objet en C++
Partie 4: Fonctions - Programmation orientée objet en C++
 
Introduction à C++
Introduction à C++Introduction à C++
Introduction à C++
 
Partie 10: Classes Génériques — Programmation orientée objet en C++
Partie 10: Classes Génériques — Programmation orientée objet en C++Partie 10: Classes Génériques — Programmation orientée objet en C++
Partie 10: Classes Génériques — Programmation orientée objet en C++
 

Similaire à Partie 12: Polymorphisme — Programmation orientée objet en C++

Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Aurélien Regat-Barrel
 
02 Spécificité du C++ COURS SYS SYSSSSSS
02 Spécificité du C++  COURS SYS SYSSSSSS02 Spécificité du C++  COURS SYS SYSSSSSS
02 Spécificité du C++ COURS SYS SYSSSSSSAyoubElmrabet6
 
Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Engineor
 
Les nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneLes nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneMicrosoft
 
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...cppfrug
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDidier Plaindoux
 

Similaire à Partie 12: Polymorphisme — Programmation orientée objet en C++ (12)

Polymorphisme
PolymorphismePolymorphisme
Polymorphisme
 
Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !Polymorphisme : un concept polymorphe !
Polymorphisme : un concept polymorphe !
 
cours1.ppt
cours1.pptcours1.ppt
cours1.ppt
 
cours2.ppt
cours2.pptcours2.ppt
cours2.ppt
 
cours1.ppt
cours1.pptcours1.ppt
cours1.ppt
 
POO-chapitre2.pptx
POO-chapitre2.pptxPOO-chapitre2.pptx
POO-chapitre2.pptx
 
02 Spécificité du C++ COURS SYS SYSSSSSS
02 Spécificité du C++  COURS SYS SYSSSSSS02 Spécificité du C++  COURS SYS SYSSSSSS
02 Spécificité du C++ COURS SYS SYSSSSSS
 
Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !Open close principle, on a dit étendre, pas extends !
Open close principle, on a dit étendre, pas extends !
 
Les nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ ModerneLes nouveautés de C++11 : Ecrire du C++ Moderne
Les nouveautés de C++11 : Ecrire du C++ Moderne
 
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...
Du Polymorphisme dynamique au polymorphisme statique : Abstraction sans perte...
 
De java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvementsDe java à swift en 2 temps trois mouvements
De java à swift en 2 temps trois mouvements
 
Part1
Part1Part1
Part1
 

Partie 12: Polymorphisme — Programmation orientée objet en C++

  • 1. Programmation Orientée Objet en C++ 12ème Partie: Polymorphisme Fabio Hernandez Fabio.Hernandez@in2p3.fr
  • 2. Vue d'Ensemble Notions de base Types, variables, opérateurs Contrôle d'exécution Fonctions Mémoire dynamique Qualité du logiciel Evolution du modèle objet Objets et classes Fonctions membres Classes génériques Héritage Polymorphisme Héritage multiple Entrée/sortie POO en C++: Polymorphisme 401 © 1997-2003 Fabio HERNANDEZ
  • 3. Table des Matières Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 402 © 1997-2003 Fabio HERNANDEZ
  • 4. Motivation Le mécanisme d'héritage permet aux sous-classes d'utiliser l'implémentation des méthodes de la classe de base Nous allons étudier un mécanisme étroitement lié à l'héritage appelé polymorphisme Polymorphisme signifie la possibilité d ’un objet de prendre plusieurs formes Dans le contexte du modèle objet cela signifie qu'une "entité" du langage peut être attachée en temps d'exécution à des objets de classes différentes Dans le cas de C++, cette "entité" ne peut être qu'un pointeur ou une référence POO en C++: Polymorphisme 403 © 1997-2003 Fabio HERNANDEZ
  • 5. Motivation (suite) Ce mécanisme permet de manipuler d'une façon uniforme un ensemble d'objets appartenant à une même hiérarchie de classes POO en C++: Polymorphisme 404 © 1997-2003 Fabio HERNANDEZ
  • 6. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 405 © 1997-2003 Fabio HERNANDEZ
  • 7. Affectation Polymorphe Figure OpenFigure ClosedFigure Segment Polyline Polygon Ellipse Triangle Rectangle ... Circle Square POO en C++: Polymorphisme 406 © 1997-2003 Fabio HERNANDEZ
  • 8. Affectation Polymorphe (suite) Si nous déclarons les objets Polygon aPolygon; Triangle aTriangle; Square aSquare; Nous pouvons déclarer le pointeur Polygon* polygonPtr; Et les affectations suivantes sont valides polygonPtr = &aTriangle; // aTriangle is-a Polygon polygonPtr = &aSquare; // aSquare is-a Polygon polygonPtr = new Rectangle; // a Rectangle is-a Polygon Le mécanisme d'héritage nous permet de traiter une instance de la classe Triangle ou Square comme une instance de Polygon POO en C++: Polymorphisme 407 © 1997-2003 Fabio HERNANDEZ
  • 9. Affectation Polymorphe (suite) Notez qu'il n'y a aucune transformation des objets aTriangle et aSquare une fois crée un objet ne change pas son type Les pointeurs et références peuvent être "attachés" à des objets de types différents descendants d'un ancêtre commun Pour le passage de paramètres nous pouvons utiliser le même principe soit la fonction void inspect(const Polygon& aPolygon) { // Do something with the parameter object } POO en C++: Polymorphisme 408 © 1997-2003 Fabio HERNANDEZ
  • 10. Affectation Polymorphe (suite) Nous pouvons appeler cette fonction avec comme argument un objet descendant de Polygon Square aSquare; Triangle aTriangle; inspect(aSquare); // OK: aSquare is a Polygon inspect(aTriangle); // OK: aTriangle is a Polygon Circle aCircle; inspect(aCircle); // COMPILATION ERROR: aCircle is // not a kind of Polygon POO en C++: Polymorphisme 409 © 1997-2003 Fabio HERNANDEZ
  • 11. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 410 © 1997-2003 Fabio HERNANDEZ
  • 12. Structures de Données Polymorphes Soit le tableau Polygon* polygonArray[4]; polygonArray[0] = new Rectangle; polygonArray[1] = new Square; polygonArray[2] = new Triangle; polygonArray[3] = new Polygon; Nous pouvons le visualiser comme 0 1 2 3 polygonArray POO en C++: Polymorphisme 411 © 1997-2003 Fabio HERNANDEZ
  • 13. Structures de Données Polymorphes (suite) Une structure polymorphe est une structure qui contient des objets de types différents descendants d'une classe commune Tous les conteneurs que nous avons étudiés peuvent être des structures polymorphes (List, Queue, Set, Bag, Stack, ...) L'intérêt des conteneurs polymorphes c'est qu'ils offrent la possibilité de traiter d'une façon uniforme tous les objets contenus Supposons par exemple que nous voulons calculer la somme des périmètres des polygones contenus dans notre tableau Une façon naturelle serait de faire une boucle pour parcourir chacune des positions du tableau en calculant le périmètre du polygone correspondant et d'en faire l'addition POO en C++: Polymorphisme 412 © 1997-2003 Fabio HERNANDEZ
  • 14. Structures de Données Polymorphes (suite) Calcul du périmètre (suite) float total = 0.0; for (int pos=0; pos < MaxPositions; pos++) { total += Perimeter of polygonArray[pos]; } Quelle méthode faudrait-il appeler sur l'objet pointé par polygonArray[pos] pour obtenir son périmètre? Regardons la définition de la classe Polygon POO en C++: Polymorphisme 413 © 1997-2003 Fabio HERNANDEZ
  • 15. Classe Polygon #include "Point.h" #include "List.h" class Polygon { public: // Constructors/Destructor Polygon(); ~Polygon(); // Modifiers void translate(float horizontal, float vertical); void rotate(float angle); ... POO en C++: Polymorphisme 414 © 1997-2003 Fabio HERNANDEZ
  • 16. Classe Polygon (suite) // Selectors float perimeter() const; float area() const; ... private: // Data members List<Point> vertexList_; }; POO en C++: Polymorphisme 415 © 1997-2003 Fabio HERNANDEZ
  • 17. Classe Polygon (suite) L'implémentation de la fonction membre Polygon::perimeter pourrait être float Polygon::perimeter() const { int numVertices = vertexList_.length(); float result = 0.0; for (int i=1; i < numVertices; i++) { const Point& previous = vertexList_.itemAt(i-1); const Point& current = vertexList_.itemAt(i); result += current.distanceTo(previous); } const Point& first = vertexList_.first(); const Point& last = vertexList_.last(); return result + first.distanceTo(last); } POO en C++: Polymorphisme 416 © 1997-2003 Fabio HERNANDEZ
  • 18. Classe Rectangle #include "Point.h" #include "Polygon.h" class Rectangle: public Polygon { public: side2 // Constructors/Destructor Rectangle(const Point& origin, float side1, float side2); side1 ~Rectangle(); origin // Modifiers ... POO en C++: Polymorphisme 417 © 1997-2003 Fabio HERNANDEZ
  • 19. Classe Rectangle (suite) // Selectors float perimeter() const; float area() const; float diagonal() const; ... Fonctions et données membres private: spécifiques à la // Data members classe Rectangle float side1_; float side2_; Point origin_; }; POO en C++: Polymorphisme 418 © 1997-2003 Fabio HERNANDEZ
  • 20. Classe Rectangle (suite) L'implémentation de la méthode Rectangle::perimeter est plus simple que Polygon::perimeter float Rectangle::perimeter() const { return 2*(side1_ + side2_); } Rectangle est donc une spécialisation de la classe Polygon et Rectangle::perimeter est une redéfinition de Polygon::perimeter De façon similaire pour la méthode Rectangle::area POO en C++: Polymorphisme 419 © 1997-2003 Fabio HERNANDEZ
  • 21. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 420 © 1997-2003 Fabio HERNANDEZ
  • 22. Liaison Statique Static Binding La liaison est le mécanisme utilisé par le compilateur pour déterminer quelle fonction membre appeler sur un objet qui appartient à une hiérarchie de classes lorsqu'il y a redéfinition de méthodes Exemple Rectangle rect(Point(0.0, 1.0), 10.0, 15.0); Polygon poly; float perimeter; perimeter = rect.perimeter(); // Rectangle::perimeter() is called perimeter = poly.perimeter(); // Polygon::perimeter() is called POO en C++: Polymorphisme 421 © 1997-2003 Fabio HERNANDEZ
  • 23. Liaison Statique (suite) Exemple (suite) Polygon* polyPtr = &poly; perimeter = polyPtr->perimeter(); // Polygon::perimeter() is called Rectangle* rectPtr = &rect; perimeter = rectPtr->perimeter(); // Rectangle::perimeter() is called polyPtr = &rect; perimeter = polyPtr->perimeter(); // Rectangle::perimeter() or Polygon::perimeter()? POO en C++: Polymorphisme 422 © 1997-2003 Fabio HERNANDEZ
  • 24. Liaison Statique (suite) Exemple (suite) La fonction membre appelée est Polygon::perimeter() Le principe de liaison statique établit que le type de l'objet sur lequel la méthode est appliquée détermine statiquement la méthode appelée Dans l'exemple précédent, le pointeur polyPtr pointe vers un objet de la classe Polygon; en conséquence, l'instruction polyPtr->perimeter() se traduit par une invocation à la méthode Polygon::perimeter() POO en C++: Polymorphisme 423 © 1997-2003 Fabio HERNANDEZ
  • 25. Liaison Statique (suite) De façon similaire l'instruction float diagonal = polyPtr->diagonal(); // ERROR est marquée par une erreur de compilation: polyPtr est défini comme un pointeur à Polygon et la méthode Polygon::diagonal n'est pas définie Par contre avec les instructions Rectangle* rectPtr = &rect; float diagonal = rectPtr->diagonal(); // OK on obtient le résultat souhaité Ce principe de liaison (binding) est appelé statique parce que le choix de la méthode à appeler est fait en temps de compilation POO en C++: Polymorphisme 424 © 1997-2003 Fabio HERNANDEZ
  • 26. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 425 © 1997-2003 Fabio HERNANDEZ
  • 27. Liaison Dynamique Dans l'exemple précédant du calcul du périmètre float total = 0.0; for (int pos=0; pos < MaxPositions; pos++) total += polygonArray[pos]->perimeter(); la méthode qui sera appelée pour chaque objet du tableau est Polygon::perimeter() Supposons que nous disposons d'une méthode pour connaître en temps d'exécution la classe d'un objet On pourrait écrire par exemple if (type of polygonArray[pos] == Rectangle) // WARNING: this is pseudo-code pour déterminer si un objet est de type Rectangle POO en C++: Polymorphisme 426 © 1997-2003 Fabio HERNANDEZ
  • 28. Liaison Dynamique (suite) Une façon de résoudre ce problème et d'appeler la bonne méthode serait float total = 0.0; for (int pos=0; pos < MaxPositions; pos++) { // WARNING: this is pseudo-code if (type of polygonArray[pos] == Rectangle) total += ((Rectangle*)polygonArray[pos])->perimeter(); else if (type of polygonArray[pos] == Triangle) total += ((Triangle*)polygonArray[pos])->perimeter(); .... } POO en C++: Polymorphisme 427 © 1997-2003 Fabio HERNANDEZ
  • 29. Liaison Dynamique (suite) L'inconvénient de cette technique c'est qu'elle rend difficile les modifications Si une nouvelle sous-classe de Polygon est rajoutée ou une sous-classe existante est supprimée de la hiérarchie, cette boucle doit être modifiée Le modèle objet propose une technique pour résoudre ce problème appelée "Liaison Dynamique" (dynamic binding) Par opposition au principe de liaison statique, avec la liaison dynamique le compilateur ne peut décider en temps de compilation quelle méthode appeler. Cette décision est prise en temps d'exécution, par rapport à la classe de l'objet en question (Rectangle, Triangle, Polygon, ...) POO en C++: Polymorphisme 428 © 1997-2003 Fabio HERNANDEZ
  • 30. Liaison Dynamique (suite) Contrairement à d'autres langages OO, C++ utilise par défaut la liaison statique Le programmeur est donc responsable d'informer le compilateur que pour une ou plusieurs méthodes d'une classe il souhaite utiliser la liaison dynamique Le mot clé du langage pour exprimer ce concept est virtual Nous devons en conséquence modifier l'interface de notre classe Polygon pour indiquer que la fonction membre Polygon::perimeter sera virtual POO en C++: Polymorphisme 429 © 1997-2003 Fabio HERNANDEZ
  • 31. Classe Polygon class Polygon { public: // Constructors/Destructor ... // Modifiers ... // Selectors Définition des virtual float perimeter() const; fonctions membres virtual float area() const; Perimeter et area ... comme ayant liaison dynamique private: // Data members ... }; POO en C++: Polymorphisme 430 © 1997-2003 Fabio HERNANDEZ
  • 32. Classe Polygon (suite) Notez que l'implémentation des fonctions Polygon::perimeter et Polygon:: area reste inchangée Les interfaces des sous-classes de Polygon (Rectangle, Triangle, ...) peuvent rester inchangées. Néanmoins, pour clarté nous allons propager la modification de l'interface de Polygon à toutes ses sous-classes Regardons le cas de la classe Rectangle POO en C++: Polymorphisme 431 © 1997-2003 Fabio HERNANDEZ
  • 33. Classe Rectangle class Rectangle: public Polygon { public: Propagation pour // Constructors/Destructor clarté de la ... définition des // Modifiers fonctions membres ... Perimeter et area // Selectors comme virtual. virtual float perimeter() const; virtual float area() const; Définition de la virtual float diagonal() const; méthode diagonal ... comme virtual. private: Affecte toutes les // Data members sous-classes de ... Rectangle }; POO en C++: Polymorphisme 432 © 1997-2003 Fabio HERNANDEZ
  • 34. Calcul du périmètre Dans l'exemple du tableau polymorphe 0 1 2 3 l'algorithme float total = 0.0; for (int pos=0; pos < MaxPositions; pos++) total += polygonArray[pos]->perimeter(); appellera Rectangle::perimeter(), Square::perimeter(), Triangle::perimeter() et Polygon::perimeter() POO en C++: Polymorphisme 433 © 1997-2003 Fabio HERNANDEZ
  • 35. Destructeur Virtuel Lors de la destruction d'une structure (conteneur) polymorphe (List, Queue, Stack, Set, Bag, Tree, ...) les objets contenus seront eux aussi probablement détruits Le destructeur de chacun des objets sera utilisé for (int pos=0; pos < MaxPositions; pos++) delete polygonArray[pos]; Cependant, avec le destructeur nous avons le même problème que avec la fonction membre perimeter dans ce cas particulier, à cause de la liaison statique uniquement le destructeur Polygon::~Polygon() sera appelé La solution est la même que pour les autres fonctions membres Le destructeur de la classe de base doit être défini virtual POO en C++: Polymorphisme 434 © 1997-2003 Fabio HERNANDEZ
  • 36. Destructeur Virtuel (suite) class Polygon { public: // Constructors/Destructor Polygon(); virtual ~Polygon(); Le destructeur doit être déclaré // Modifiers virtual. ... // Selectors ... private: // Data members ... }; POO en C++: Polymorphisme 435 © 1997-2003 Fabio HERNANDEZ
  • 37. Destructeur Virtuel (suite) De façon similaire, pour des raisons de clarté nous déclarerons virtual le destructeur de toutes les sous-classes de Polygon D'une façon générale, on doit déclarer virtual le destructeur de toute classe contenant au moins une fonction membre virtuelle POO en C++: Polymorphisme 436 © 1997-2003 Fabio HERNANDEZ
  • 38. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 437 © 1997-2003 Fabio HERNANDEZ
  • 39. Méthodes Abstraites Supposons que nous voulons ajouter une méthode à la classe Polygon pour déterminer si un point (x,y) se trouve à l'intérieur Le prototype de cette méthode pourrait être bool Polygon::isInside(const Point& aPoint) const Un tel service est facilement implémenté pour certaines sous- classes de Polygon (Triangle, Rectangle, Square) L'implémentation est plus difficile pour un polygone générique une implémentation par défaut n'est pas souhaitable Il est néanmoins nécessaire que tous les polygones, c'est à dire toutes les sous-classes de Polygon fournissent sa propre implémentation de ce service POO en C++: Polymorphisme 438 © 1997-2003 Fabio HERNANDEZ
  • 40. Méthodes Abstraites (suite) Une façon de faire c'est d'implémenter le service dans la classe de base avec une implémentation par défaut "vide" bool Polygon::isInside(const Point& aPoint) const { cerr << "You must implement this routine" << endl; return false; } Une autre façon de faire c'est de forcer chaque sous-classe à fournir ce service en déclarant la méthode comme abstraite dans la classe de base Une méthode abstraite est une méthode pour laquelle la classe de base ne fournit pas d'implémentation POO en C++: Polymorphisme 439 © 1997-2003 Fabio HERNANDEZ
  • 41. Méthodes Abstraites (suite) Nous pouvons définir la méthode Polygon::isInside comme abstraite Une méthode abstraite en C++ est aussi appelée virtuelle pure POO en C++: Polymorphisme 440 © 1997-2003 Fabio HERNANDEZ
  • 42. Méthodes Abstraites (suite) class Polygon { public: // Constructors/Destructor Méthode Abstraite ... ou virtuelle pure // Modifiers ... // Selectors virtual bool isInside(const Point& aPoint) const = 0; ... private: // Data members ... }; POO en C++: Polymorphisme 441 © 1997-2003 Fabio HERNANDEZ
  • 43. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 442 © 1997-2003 Fabio HERNANDEZ
  • 44. Classe Abstraite Une classe ayant au moins une méthode abstraite est appelée classe abstraite Il est impossible de créer une instance d'une classe abstraite Cette vérification est effectuée par le compilateur Polygon aPolygon; // ERROR: Polygon has at least one pure virtual // member fonction Les sous-classes (instanciables) de Polygon doivent fournir une implémentation de cette méthode POO en C++: Polymorphisme 443 © 1997-2003 Fabio HERNANDEZ
  • 45. Classe Abstraite (suite) class Rectangle: public Polygon { public: // Constructors/Destructor ... // Modifiers ... // Selectors virtual bool isInside(const Point& aPoint) const; ... private: // Data members ... }; POO en C++: Polymorphisme 444 © 1997-2003 Fabio HERNANDEZ
  • 46. Classe Abstraite (suite) bool Rectangle::isInside(const Point& aPoint) const { if ((origin_.getX() <= aPoint. getX()) && (aPoint. getX() <= (origin_. getX() + side1_)) && (origin_.getY() <= aPoint. getY()) && (aPoint. getY() <= (origin_. getY() + side2_))) return true; return false; } POO en C++: Polymorphisme 445 © 1997-2003 Fabio HERNANDEZ
  • 47. Contrôle d'Avancement Motivation Affectation polymorphe Structures de données polymorphes Liaison statique Liaison dynamique Méthodes abstraites Classes abstraites Résumé POO en C++: Polymorphisme 446 © 1997-2003 Fabio HERNANDEZ
  • 48. Résumé Le polymorphisme permet à une référence ou à un pointeur d'être associé en temps d'exécution à des instances de classes différentes La liaison dynamique est le mécanisme qui permet de déterminer en temps d'exécution l'utilisation de la redéfinition correcte d'une méthode Une méthode abstraite ou virtuelle pure est une méthode pour laquelle la classe de base ne fournit pas d'implémentation Une classe avec une ou plusieurs méthodes abstraites est elle aussi abstraite Il est impossible de créer une instance d'une classe abstraite POO en C++: Polymorphisme 447 © 1997-2003 Fabio HERNANDEZ