IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Notions C++:Polymorphisme,Virtual,Heritage,Typage dynamique :par l'exemple?


Sujet :

C++

Vue hybride

observ Notions... 03/09/2006, 06h37
Alp Salut, N'ayant pas le... 03/09/2006, 09h11
koala01 Salut, De manière... 03/09/2006, 13h27
Luc Hermitte a- En regroupant définitions... 04/09/2006, 01h10
Jean-Marc.Bourguet Si tu considères les types... 04/09/2006, 17h56
Jean-Marc.Bourguet Non, l'idée d'une virtuelle... 04/09/2006, 17h50
Jean-Marc.Bourguet J'ai commencé à répondre mais... 04/09/2006, 17h48
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 11
    Par défaut Notions C++:Polymorphisme,Virtual,Heritage,Typage dynamique :par l'exemple?
    Bonjour,


    Je me remets à vous pour m'eclaircir avec des exemples succintes redigés par vos propres soins et qui demontrent ces mecanismes .ce sont des notions que j'utilise sans vraiment les maïtriser.

    --------------------------VIRTUAL------------------------------------

    Il suffit d'une seule fonction virtuelle pure pour rendre une classe abstraite donc non instanciable.Est ce qu'une classe avec une methode virtuelle "non" pure est instanciable (je connais la reponse:instanciable) mais surtout à quoi ça sert les fonctions virtuelles non pures et comment s'utilisent leurs classes (un exemple peut être ).

    -----------------------------------------------------------------------


    ---------------------------POLYMORPHISME----------------------------

    Le polymorphisme comme je l'entends (!! vrai ou faux?) ne peut être evoqué sans passer par un heritage:donner à la classe mère plusieurs formes par l'instanciation de ses clesses derivées dans lesquelles on specialise les methodes virtuelles .
    Donc est-ce qu'on est obligé de partir d'une classe abstraite pour par la suite redefinir les methodes dans les classes filles pour illustrer le polymophisme?

    un exemple de polymophisme?

    -------------------------------------------------------------------------

    -------------------------Typage dynamique-----------------------------

    C'est quoi ?
    ça s'utilise comment?
    un exemple de typage dynamique

    Merci à vous tous...

  2. #2
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Salut,

    N'ayant pas le temps de te répondre là, je veux juste te demander si tu as consulté la FAQ C++, car il risque d'y avoir pas mal de réponses et exemples dedans. Dans le genre, tu peux aussi chercher sur google "FAQ C++ Lite", "FAQ Comeau C++", "FAQ FCLC++".
    Toutes ces FAQ apporteront surement les réponses que tu cherches.

    Toute fois si cela ne suffit pas, je pense bien que des personnes répondront

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    De manière générale, les méthodes virtuelles pures, les classes abstraites, et le polymorphisme sont intimement liées...

    L'idée d'une méthode virtuelle pure, c'est de dire que l'on décide de ne pas implémenter la méthode pour la classe que l'on est en train de créer parce que la classe est trop générique pour savoir exactement comment la méthode devra etre implémentée.

    On décide de travailler de la sorte quand on veut indiquer que toutes les classes dérivée de notre classe générique disposeront d'une méthode bien précise, et que l'on ne sait pas, a priori, pour quelle classe dériviée la méthode sera appelée.

    En déclarant une méthode virtuelle pure, on déclare de facto une classe abstraite, c'est à dire non instanciable (car on ne peut pas instancier une classe dont on ne sait pas comment réagit l'une de ses méthodes).

    Cela ne t'empechera cependant pas de créer, au sein de ta classe de base, des fonction virtuelles qui seront correctement implémentée

    Un exemple serait la méthode de "reproduction" des "etres vivants"

    Entre les bactéries qui se reproduisent par division cellulaire, les poissons dont la femelle pond des oeufs non fécondés, et qui sont ensuite fécondés par le male, les oiseau et la plupart des reptiles qui pondent des oeuf fécondés précédemment, et les mamifères qui gardent les oeufs fécondés en eux jusqu'au terme de la gestation, comment pourrais tu implémenter la méthode "Reproduction" d'une classe "EtresVivants"?

    Comme les classes "Bacteries","Poisson","Oiseaux","Reptiles" et "Mamiferes" ériteront toutes de la classe (devenue abstraite, du fait de la méthode non implémentée) "EtreVivants", elles disposeront toutes d'une méthode "Reproduction", héritée de la classe "EtreVivants".

    Comme tu sais comment implémenter cette méthode, et qu'en plus, si tu ne le fais pas, tu créera une nouvelle classe abstraite (une meme cause ayant les memes effets ) tu pourras (devras si tu veux pouvoir instancier ta classe dérivée) l'implémenter.

    Cette implémentation, différente en fonction de la classe dérivée, fera apparaitre le phénomene du polymorphisme (qui signifie tout simplement "une meme action produit des effets différents en fonction du contexte dans lequel elle est effectuée).

    Un exemple beaucoup plus pratique concernant le polymorphisme est l'exemple des structures dynamiques (pile, file, liste)...

    L'idée est de pouvoir rajouter dynamiquement un objet à un des bout de la structure (pour la création d'une chaine de caractères d'une taile inconnue, par exemple?)

    Chaque élément de la pile, file ou liste sera composé de la meme manière, à savoir

    - Un membre permettant de garder l'information (on va dire, pour l'exemple, un caractère)
    - Un membre permettant d'accéder à l'élément suivant de la liste (un pointeur sur l'élément suivant)

    Seulement, chaque élément risque de réagir différemment selon sa place au sein de la liste:
    -le premier élément n'aura pas de valeur et servira de "borne de départ"
    -Le dernier élément n'aura pas de valeur (ou une valeur "\0"), n'aura pas de membre permettant d'accéder à l'élément suivant et servira de "borne d'arrivee"
    -Tous les points entre le premier et le dernier éléments DOIVENT avoir une valeur.

    Bien que ce ne soit pas *forcément* l'idéal, nous utiliserons grandement la récursivité pour faire fonctionner le système (même si la récursivité n'apparait pas forcément comme telle)

    On créerait donc une premiere classe générique qui fournirait l'ensemble des méthodes qui seront identiques pour les trois catégories (et qu'on retrouve réellement dans chacune d'elle) On va nommer cette classe IListItem.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    class IListItem
    {
        //Les classes dérivées doivent accéder aux méthodes, on les place donc
        // en protected
        //constructeurs et destructeurs ne font rien dans notre cas
        public:
            IListItem(){};
            virtual ~IListItem(){};
        protected:
            virtual unsigned int count()=0//méthode permettant d'obtenir le nombre 
                                  //d'éléments a implémenter dans chacune des classes
                                  //dérivée
            virutal IListItem* Add(char value)=0;//méthode permettant
                                 //de rajouter un élément à la fin de la file
        //surcharge de quelques operateurs utiles
            virtual char& operator[](unsigned int num)=0;
            virtual IListItem* operator++()=0;
        //itérateurs sur le début et la fin de la liste
            IListItem* Debut()=0;
            IListItem* Fin()=0;
    };
    Comme tu peux le remarquer, il n'y a aucun membre, et toutes les méthodes sont virtuelles pures...
    Nous allons maintenant créer la classe pour les éléments "centraux" de la liste
    (nommons la CentreItem)
    Il contiennent les deux membres, et implémentent chacune des méthodes créés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    //déclaration de la classe
    class CentreItem:public IListItem
    {
        public:
        //le constructeur que l'on va utiliser
            CentreItem(char value, IListItem* suivant);
            virtual ~CentreItem();
        //déclaration des méthodes virtuelles pures
           virtual unsigned int Count();
           virtual IListItem* Add(char value);
           virtual char& operator[](unsigned int i);
           virtual IListItem* operator++(IListItem* i);
        //l'itérateur Debut passe en privé (inaccessible depuis un CentreItem), mais 
        //literateur Fin est accessible
           virtual IListItem* Fin();
        //les membres de cette classe
           char Valeur;
        //l'élément Suivant est polymorphique... raison pour laquelle il prend le type
        // de la classe de base
           IListItem* Suivant;
        private:
           virtual IListItem* Debut(){};
    };
    //implémentation
    //du constructeur utilisé
    CentreItem::CentreItem(char value, IListItem *suivant)
    {
        Valeur=value;
        Suivant=suivant;
    }
    // du destructeur (qui libère la mémoire de l'élément suivant
    CentreItem::~CentreItem()
    {
        delete Suivant;
        Suivant=NULL;
    }
    // de l'opérateur ++
    IListItem* CentreItem::operator++()
    {
        return Suivant;
    }
    // de l'operateur []
    char& CentreItem::operator[](unsigned int i)
    {
    // renvoie this si c'est l'élément attendu, sinon, appelle operator[] sur 
    //l'élément suivant
        if(i==0)
            return Valeur;
        return Suivant->operator[](i-1);
    }
    //de l'itérateur sur la fin de liste
    IListItem* Fin()
    {
    //appel récursif sur Suivant->Fin()
        return Suivant->Fin();
    }
    //de la méthode Add()
    IListItem* Add(char value)
    {
    // Appelle Suivant->Add() et renvoie this
        Suivant=Suivant->Add(value);
        return this;
    }
    //de la méthode Count()
    unsigned int Count()
    {
    //renvoie le résultat de Suivant->count(), incrémenté de 1
        return (Suivant->Count()+1);
    }
    Nous allons maintenant créer la classe de fin de liste (nommons la TailList)
    Elle n'a pas de membres, mais va servir à la sécurisation de la liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    class TailList
    {
        public:
        //constructeurs et destructeurs qui ne font rien
            TailList(){};
            virtual ~TailList(){};
        //operateur [] et ++ qui lancent une exception
            virtual char& operator[](unsigned int i){throw std::invalid_argument("indice hors limites");}
     
            virtual operator++(){throw std::invalid_argument("indice hors limites");}
        //la méthode Add() (implémentée plus loin ;) )
            IListItem*Add(char value);
        //Fin() renvoie this;
        virtual IListItem* Fin(){return this;}
        //ajout des opérateur d'(in)égalité
            virtual bool operator==(IListItem* i){return (this==i);}
            virtual bool operator!=(IListItem*){return (this!=i);}
        //peut etre voudra tu rajouter des méthodes propres aux éléments de ta liste
        private:
        //Debut n'est pas accessible et ne fait rien
            virtual IListItem* Debut(){};
    };
    // implémentation de la méthode Add
    IListItem* TailList::Add(char value)
    {
    // crée un nouvel élément de type CentreItem et le renvoie
        CentreItem *nouveau=new CentreItem(value,this);
        return nouveau;
    }
    Il ne reste plus qu'à créer une classe pour la tete de liste (nommée TeteListe)...
    Elle ne dispose que d'un seul membre: Suivant, mais fournis les méthodes qui permettent d'accéder aux autres éléments
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    class TeteListe:public IListItem
    {
        public:
        //constructeurs et destructeurs (implémentés plus loin)
            TeteListe();
            virtual ~TeteListe();
        //sécurisation de Add: une nouvelle méthode qui récupère l'exception
        //(implémentée plus loin)
            virtual bool Insert(char value);
        //La méthode Count()
            virtual unsigend int Count(){return Suivant->Count();}
        //les opérateurs 
            virtual char& operator[](unsigned int i){return Suivant->operator[](i);}
        //Implémentation des itérateurs
            IListItem* Debut(){return Suivant;}
            IListItem* Fin(){rerturn Suivant->Fin();}
        //Le seul membre utilisé
            IListItem* Suivant;
        private:
        //La méthode Add() (implémentée plus loin)
            virtual IListItem* Add(char value);
    };
    //l'implémentation
    //Du construteur
    TeteListe::TeteListe()
    {
        //initialise Suivant comme fin de liste
        Suivant=new TailList();
    }
    //du destructeur
    TeteListe::~TeteListe()
    {
        //libere la mémorie de suivant
        delete Suivant;
        Suivant=NULL;
    }
    //de la méthode Add()
    ListItem* TeteListe::Add(char value)
    {
        Suivant=Suivant->Add(value);
        return this;
    }
    //de la méthode insert
    bool TeteListe::Insert(char value)
    {
       bool ok=true;
       try
       {
           Add(value);
       }
       //récupération de l'exception  si elle survient
       catch(...)
       {
             ok=false;
       }
       return ok;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    a- En regroupant définitions et propriétés on a :
    A est abstraite
    <=> A dispose d'au moins une fonction membre virtuelle pure
    <=> A est non instanciable

    Autrement dit, la présence d'une fonction membre virtuelle non pure ne suffit pas à garantir l'instanciabilité

    b- Le polymorphisme d'inclusion, tel que pratiqué en C++, est fortement lié à l'héritage (public !). C'est quand tu peux utiliser un objet d'une classe fille là où tu attends un objet de la classe mère.
    La virtualité n'est pas nécessaire. Fréquente, mais non nécessaire. Tu peux très bien dériver une classe qui ne dispose d'aucune fonction membre virtuelle pour lui rajouter de nouvelles fonctions.
    Dans ce cas, je crois que l'on parle de sous-typage, alors que dans le cas de la supplantation d'une fonction membre virtuelle, on parle de specialisation -- à confirmer.

    Dans l'absolu, le polymorphisme désigne plus de choses que juste le polymorphisme d'inclusion. Le truc est que les langages OO ont "piraté" le terme dans leur contexte.

    c- J'avoue que c'est un terme que je n'emploie jamais. Du coup, je peux très bien le connaitre sous une autre appelation.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Luc Hermitte
    Dans ce cas, je crois que l'on parle de sous-typage,
    Si tu considères les types comme des ensembles, un sous-type est un type contenu dans un autre.

    alors que dans le cas de la supplantation d'une fonction membre virtuelle, on parle de specialisation -- à confirmer.
    J'ai l'impression mais ce n'est pas un mot que j'utilise beaucoup. Je ne l'ai pas trouvé dans les index de mes bouquins sur les types.

  6. #6
    Membre expérimenté
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Par défaut
    Je ne suis pas très à l'aise avec le terme "polymorphisme d'inclusion".

    Il semble que vous le rapprochiez (JM et Luc) à l'utilisation de l'héritage.

    Est-ce que ce terme est à rapprocher du terme "polymorphisme dynamique" ?

    Et si oui (mon terme est peut être imprécis), quel serait le terme à rapprocher au "polymorphisme statique" que s'assimile à utilisation en C++ des templates ?

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par koala01
    L'idée d'une méthode virtuelle pure, c'est de dire que l'on décide de ne pas implémenter la méthode pour la classe que l'on est en train de créer parce que la classe est trop générique pour savoir exactement comment la méthode devra etre implémentée.
    Non, l'idée d'une virtuelle pure c'est d'imposer aux descendants de la supplanter. La classe déclarant une fonction virtuelle pure peut (mais n'est pas obligée) la définir.

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    J'ai commencé à répondre mais le résultat est vraissemblablement un peu
    trop long et trop théorique. Pour ceux que ça intéresse, ce
    document donne ma
    compréhension de la chose. Tous les commentaires m'intéressent.

    J'ai du mal à comprendre la première question. C'est les fonctions
    virtuelles pures qui devraient poser un problème Les fonctions
    virtuelles non pures permettent d'introduire du typage dynamique dans un
    langage qui est essentiellement typé statiquement. Autrement dit, un appel
    virtuel permet d'appeler le membre du type réel plutôt que du type déclaré.
    Dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct A { 
       virtual void f();
    };
    struct B: A {
       virtual void f();
    };
    ...
       A* ptr = new B;
       ptr->();
    ...
    c'est B::f() qui est appelé et pas A::f() parce que bien que ptr
    soit déclaré comme pointant vers un A, il pointe en réalité vers un B et
    que f() est virtuelle.

    Pour le polymorphisme, j'ai du mal à ne pas t'envoyer vers
    le document que j'ai écrit: en résumé, il y a plusieurs
    types de polymorphisme. Mais non, on n'est pas obligé de
    partir d'une classe abstraite.

    Pour le typage dynamique, c'est quand le type de l'objet est
    indiqué dans sa valeur.

Discussions similaires

  1. Polymorphisme et heritage
    Par faico dans le forum Langage
    Réponses: 8
    Dernier message: 26/08/2006, 19h13
  2. [VBA-E]actualisation d'un tableau dynamique par macro
    Par illight dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 18/04/2006, 16h37
  3. [JSTL] Test dynamique par rapport à un paramètre
    Par cosmos38240 dans le forum Taglibs
    Réponses: 3
    Dernier message: 21/12/2005, 20h05
  4. Réponses: 2
    Dernier message: 14/11/2005, 16h04
  5. [Débat] Que pensez-vous des langages à typage dynamique?
    Par Eusebius dans le forum Langages de programmation
    Réponses: 14
    Dernier message: 16/06/2004, 12h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo