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 :

Probleme avec le polymorphisme (si c'en est vraiment)


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Points : 10
    Points
    10
    Par défaut Probleme avec le polymorphisme (si c'en est vraiment)
    Bonjour,

    J'ai quelques bases (qui datent de mes études) en Java et je me lance dans le C++.
    De mémoire, il est possible de faire ceci en Java :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ClasseDeBase toto = ClasseDerivee();
    ou
    ClasseDerivee toto = ClasseDeBase();
    et je cherche donc à faire la même chose en C++ (si c'est possible).

    J'ai une fonction qui analyse une string qui contient une trame GPS et renvoie un objet contenant les informations adéquates.
    Le problème, c'est qu'il existe différents types de trame et que le fonction doit renvoyer le bon objet en fonction du type de trame.

    Cela ressemblerais à ça :
    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
     
    GPSSentence GPSSentenceAnalyser::analyse(string gpsSentence) const{
        string gpsSentenceType = gpsSentence.substr(1, 5);
     
        if (gpsSentenceType=="GPGAA"){
            GPSSentence result = GPGAA();
            result.getNbField();
     
        }
        if (gpsSentenceType=="GPGSA"){
            GPSSentence result = GPGSA();
            result.getNbField();
        }
        if (gpsSentenceType=="GPGSV"){
            GPSSentence result = GPGSV();
            result.getNbField();
        }
        if (gpsSentenceType=="GPGLL"){
            GPSSentence result = GPGLL();
            result.getNbField();
        }
     
        return result;
     
    }
    Comment obtenir ce genre de comportement ?
    Cela est-il bien du polymorphisme ?

    Merci d'avance pour vos réponses.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Une différence importante entre la Java et le C++, c'est qu'en C++ l'utilisation de pointeurs doit être explicite, là où elle est implicite en Java.
    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseDeBase toto = ClasseDerivee();
    Ne marchera pas en C++ (ou ne fera pas ce que tu penses), si un objet est typé ClasseDeBase, c'est un ClasseDeBase et rien d'autre. Par contre, un pointeur déclaré comme pointant sur une ClasseDeBase peut en réalité pointer sur une ClasseDérivée.

    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ClasseDeBase *toto = new ClasseDerivee(); // Ne pas oublier le delete quelquepart
    // Ou pour gérer la durée de vie de l'objet pointé
    std::unique_ptr<ClasseDeBase> toto (new ClasseDérivée());
    Par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseDerivee toto = ClasseDeBase();
    Ca, ça ne marche ni en C++, ni en Java, à moins de faire du downcast, qui est souvent signe d'un design bancal (même si j'ai l'impression que cette pratique est plus acceptée dans le monde Java que dans le monde C++).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Même en JAVA, c'est n'importe quoi, on doit toujours utiliser "new".

  4. #4
    Membre à l'essai
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Points : 10
    Points
    10
    Par défaut
    @ JolyLoic
    Merci pour les infos.
    Apparemment std::unique_ptr<ClasseDeBase> toto (new ClasseDérivée()); est C++11. Je vais donc l'utiliser de préférence.

    @bacelar
    C'est vrai. Ma mémoire me joue des tours.

    Pour les suivants qui se poseraient la même question :
    Un article Wikibooks en anglais qui traite du sujet

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je viens ajouter un "petit" détail.
    Les références acceptent le polymorphismes comme les pointeurs.

    Ainsi, le code suivant se comporte comme souhaité (affichage de "1,2,3")
    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
    class base {
    public:
        virtual int valeur() const {return 0;}
    };
     
    class fille1 : public base {
    public:
        virtual int valeur() const {return 1;}
    };
     
    class fille2 : public base {
    public:
        virtual int valeur() const {return 2;}
    };
     
    int main() {
        base b;
        fille1 f1;
        fille2 f2;
     
        base& ref0=b;
        base& ref1=f1;
        base& ref2=f2;
     
        std::cout << ref0.valeur() << ',' << ref1.valeur() << ',' << ref2.valeur() << std::endl;
        return 0;
    };
    Ca devient surtout utile pour les fonctions.
    Avec les mêmes classes, ce code donne bien le même affichage que le précédent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // les classes
     
    int f(base const& ref) {
        return ref.valeur();
    }
     
    int main() {
        base b;
        fille1 f1;
        fille2 f2;
     
        std::cout << f(b) << ',' << f(f1) << ',' << f(f2) << std::endl;
        return 0;
    };
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Membre à l'essai
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Points : 10
    Points
    10
    Par défaut
    Donc, si je comprends bien, on ne peut faire du polymorphisme dynamique que via des pointers, des smart pointers et références ?
    Le polymorphisme "à la Java" est donc impossible. Est-ce dû au fait que C++ accepte l'héritage multiple et non Java ?

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Porkipic Voir le message
    Donc, si je comprends bien, on ne peut faire du polymorphisme dynamique que via des pointers, des smart pointers et références ?
    Oui

    Citation Envoyé par Porkipic Voir le message
    Le polymorphisme "à la Java" est donc impossible. Est-ce dû au fait que C++ accepte l'héritage multiple et non Java ?
    Non, ça n'a aucun rapport. C'est dû au fait qu'en Java, tout est pointeur, et que donc la notation ne fait pas apparaître explicitement qu'il y a des pointeurs partout. Par exemple dans le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class A
    {
    public: 
      int i1;
    };
     
    class B
    {
    public:
      int i2;
      A a;
    };
    Si on crée un objet de la class B, en C++, il occupera une seule zone mémoire, assez grande pour contenir 2 int i2 et i1, un venant directement de B, l'autre pour celui inclus par A.
    Le code équivalent en Java occupera 2 emplacement mémoires différents (d'ailleurs, dans le constructeur de B, on verra un new A), un contenant un entier (i2) et un pointeur (a), l'autre contenant un entier i1, pointé par le premier. Plusieurs B pourraient donc partager le même A, ce qui ne serait pas possible pour cet exemple en C++. Est-ce plus clair ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    Membre à l'essai
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Points : 10
    Points
    10
    Par défaut
    OK, je pense comprendre.
    En C++ l'inclusion d'un objet dans un autre est "réelle". Un objet A indépendant est créé, puis inclut dans B.
    En Java c'est un pointeur qui est créé, puis celui-ci est inclus dans B.

    Donc ce code imiterait le comportement Java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B
    {
    public:
      int i2;
      A* a;
    };

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [libraries] problemes avec le polymorphisme
    Par ikeas dans le forum Langage
    Réponses: 22
    Dernier message: 04/12/2014, 16h51
  2. problem avec programme polymorphisme
    Par domxaline dans le forum Débuter avec Java
    Réponses: 15
    Dernier message: 05/02/2010, 15h25
  3. Réponses: 0
    Dernier message: 05/03/2009, 13h59
  4. Réponses: 14
    Dernier message: 09/05/2006, 15h23
  5. [bmp]probleme avec les images dont la largeur est >256
    Par delfare dans le forum Développement 2D, 3D et Jeux
    Réponses: 8
    Dernier message: 15/02/2006, 16h59

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