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++/CLI Discussion :

Polymorphisme d'une sous classe vs. un membre de classe


Sujet :

C++/CLI

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut Polymorphisme d'une sous classe vs. un membre de classe
    Bonjour à toutes et à tous,

    Je débute en C++, et je souhaiterais savoir comment appeler la bonne fonction lorsque je déclare un membre de classe d'un type 'Base' (superclasse) et que je lui assigne une sous-classe dérivée.
    Une illustration:

    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
    Class Animal {};
     
    Class Chat:public Animal{
      public: 
        foo_chat();
    };
     
    Class Chien:public Animal{
      public: 
        foo_chien();
    };
     
    Class Simulation {
      private:
        Animal mon_animal;
        Un_type_sympa T;
     
      public:
        int main(void){
          mon_animal = Chat();
          T.compte_les_poils_de(mon_animal);
        }
    }
    avec:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Un_type_sympa{
      public:
        int compte_les_poils_de(Animal a) {return 0};
        int compte_les_poils_de(Chien a) {return 10};
        int compte_les_poils_de(Chat a) {return 20};
    };

    Dans mon exemple, c'est toujours 0 qui est retourné par compte_les_poils_de(), ce qui est normal, vu que mon_animal est déclaré en tant que Animal, mais comment faire pour que Un_type compte le bon nombre de poils en fonction de la classe (Chien, Chat?). Je peux m'en sortir par des conditions if else, et caster mais je suis certain qu'une solution plus élégante existe. J'ai regardé les fonctions virtuelles, les pointeurs, etc. mais je n'ai pas réussi à faire fonctionner comme il faut.

    Merci!

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Il y a plein de moyens, mais pourquoi avoir plusieurs méthodes ???

    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
    Class Animal {
    protected :
        int m_poils = 0;
    public :
        int GetPoils(){return m_poils;}
    };
     
    Class Chat:public Animal{
      public: 
        Chat:m_poils{20}();
    };
     
    Class Chien:public Animal{
      public: 
        Chien:m_poils{10}();();
    };
     
    class Un_type_sympa{
      public:
        int compte_les_poils_de(Animal a) {return a.GetPoils();};
    };
     
    Class Simulation {
      private:
        Animal mon_animal;
        Un_type_sympa T;
     
      public:
        int main(void){
          mon_animal = Chat();
          T.compte_les_poils_de(mon_animal);
        }
    }
    Si vous voulez vraiment vous la péter avec de la résolution dynamique de méthode :

    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
    Class Animal {
    protected :
    public :
        virtual int GetPoils(){return 0;}
    };
     
    Class Chat:public Animal{
      public: 
        int GetPoils() override{return 20;}
    };
     
    Class Chien:public Animal{
      public: 
        int GetPoils() override{return 10;}
    };
     
    class Un_type_sympa{
      public:
        int compte_les_poils_de(Animal a) {return a.GetPoils();};
    };
     
    Class Simulation {
      private:
        Animal mon_animal;
        Un_type_sympa T;
     
      public:
        int main(void){
          mon_animal = Chat();
          T.compte_les_poils_de(mon_animal);
        }
    }
    P.S.: vous n'êtes absolument pas dans le bon forum :
    https://www.developpez.net/forums/f19/c-cpp/cpp/

  3. #3
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut
    Merci pour ce retour rapide et efficace.

    Pour répondre à la question, la fonction "compte_les_poils_de" est un calcul qui dépend du type de l'animal. On peut imaginer que l'approche pour compter les poils sur un chat, un serpent, une mangouste, est différente: ca dépend de la dimension de la bête et son espèce par exemple. C'est comme ca que j'illustrerais mon problème (qui n'a que peu a voir avec les animaux à la base).
    Ce qui fait que le_Type_sympa doit bien choisir sa méthode pour procéder au calcul de manière à être optimal!

    Je peux effectivement faire comme dans les 2 exemples donnés (merci!), et implémenter le calcul dans les animaux directement.
    A titre de curiosité, comment aurais-je fais pour déplacer le problème dans Un_type_sympa (comme initialement proposé)?
    J'ai aussi une contrainte de temps d'execution (bcp d'itérations car beaucoup de paquets de poils), Est-ce que la résolution dynamique de méthode est plus efficiente?

    Merci

    Edit: ah oui mince, il faudrait que je puisse bouger le topic vers la section C++

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    @Bacelar: Ça compile, une classe abstraite contenue par valeur?
    Je pense que tu as oublié un & quelque part.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre confirmé
    Inscrit en
    Février 2013
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Février 2013
    Messages : 94
    Par défaut
    Pour la petite information, j'ai utilisé une classe abstraite (pure) avec un pointeur (class Animal), et ca marche.
    Mais je reste intéressé par la demande initiale: si le membre est d'un type (classe de base) et que c'est en fait un objet de type classe dérivée, comment fait Un_Type_Sympa pour trouver le 'vrai' type du paramètre (cad la classe dérivée par la classe de base)?

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ça ne marche qu'avec les pointeurs et références, et ça vient du fait qu'une classe contenant au moins une fonction membre virtuelle possède un pointeur caché vers ce qu'on appelle la vtable. En fait, quand tu écris ceci:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Class Animal {
    protected :
    public :
        virtual int GetPoils(){return 0;}
    };
     
    Class Chat:public Animal{
      public: 
        int GetPoils() override{return 20;}
    };
     
    void affich(Animal *pAni)
    {
        cout << pAni->GetPoils() << endl;
    }

    Ça fait ça (avec quelques casts en plus):
    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 AnimalVtbl {
        int (Animal::*GetPoils)();
    };
     
    Class ChatVtbl : public AnimalVtbl { };
     
    Class Animal {
    protected :
        AnimalVtbl * pVtbl;
    public :
        Animal();
        int GetPoils(){return 0;}
    };
     
    Class Chat:public Animal{
      public: 
        Chat();
        int GetPoils() {return 20;}
    };
     
    AnimalVtbl global_Animal_vtbl = { &Animal::GetPoils; };
    ChatVtbl global_Chat_vtbl = { &Chat::GetPoils; };
     
    Animal::Animal() : pVtbl(&global_Animal_vtbl ) { }
    Chat::Chat() : Animal(), pVtbl(&global_Chat_vtbl ) { }
     
    void affich(Animal *pAni)
    {
        cout << pAni->*(pAni->pVtbl->GetPoils)() << endl;
    }
    Mais tout ça est un détail d'implémentation.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/11/2007, 12h28
  2. Problème avec une sous classe de Graphics2D
    Par Virgile le chat dans le forum 2D
    Réponses: 1
    Dernier message: 16/06/2007, 02h59
  3. Réponses: 1
    Dernier message: 17/11/2006, 16h57
  4. Instanciation d'une sous-classe
    Par iubito dans le forum Langage
    Réponses: 6
    Dernier message: 23/01/2006, 16h27

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