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 :

Héritage : petit problème


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 16
    Par défaut Héritage : petit problème
    Bonjour à tous,

    Mon problème en deux mots: J'aimerai pouvoir appeller une méthode d'une classe dérivé depuis un tableau de sa classe de base.
    Regardez la fonction main() dans ma source: ici, le compilo (et il a raison) me signale que la classe A n'a pas de méthode du nom de BB() même si (c'est que je suis embêté) il s'agie à la base d'une classe de type B.
    Donc: comment éviter de perdre l'accès à la méthode B() de la class BB alors que je la foue dans un vecteur de class A ! (A est la base de B)

    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
    using namespace std;
     
    class A
    {
    public:  
        void AA()
        {
            cout<<"Je suis de type A"<<endl; 
        }   
    };
     
    class B: public A
    {
    public:       
        void BB()
        {
             cout<<"Je suis de type B"<<endl; 
        }      
    };
     
    class C: public A
    {
    public:       
        void CC()
        {
             cout<<"Je suis de type C"<<endl; 
        }      
    };
     
    int main(int argc, char *argv[])
    {
        vector<A*> Vec;
        B* CB = new B;
        Vec.push_back(CB);
        Vec[0].BB();
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    Une idée ?
    Dans l'attente de vos réponses ...

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    Moi, je te conseillerais d'utiliser une méthode virtuelle, pour ça...
    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.

  3. #3
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    ton vector est de type A*
    donc en rajoutant un pointeur de B dans le vector il est converti en A*
    il ne peut donc pas appeler une fonction B,
    tu devrais utiliser le polymorphysm comme te conseil Medinoc!!

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 16
    Par défaut
    Ah ! Oui, j'y ai pensé mais, pour ce que je fais c'est pas top
    Il n'y a pas moyen de faire ce dont je parle ?

  5. #5
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    et en faisant:
    ça marcherait pas?

  6. #6
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    au fait...

    ton vect[0] est un pointeur
    donc pour appeler la fonction tu dois faire
    et non..

  7. #7
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    pourquoi ca ne t irai pas ca??
    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
     
    #include<iostream>
    #include<vector>
    using namespace std; 
     
    class A 
    { 
    public:  
        virtual void AA() 
        { 
            cout<<"Je suis de type A"<<endl; 
        }    
    }; 
     
    class B: public A 
    { 
    public:        
    	void AA() 
        { 
    		cout<<"Je suis de type B"<<endl; 
        }      
    }; 
     
    class C: public A 
    { 
    public:        
        void CC() 
        { 
    		cout<<"Je suis de type C"<<endl; 
        }      
    }; 
     
    int main(int argc, char *argv[]) 
    { 
        vector<A*> Vec; 
        B* CB = new B; 
        Vec.push_back(CB); 
    	Vec[0]->AA(); 
        system("PAUSE"); 
        return EXIT_SUCCESS; 
    }

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 16
    Par défaut
    @ d-a-v-e: Le polymorphisme ne me convient pas ici car mes classes sont trop différentes pour que je puisse regrouper leurs méthodes sous de même noms. Néanmois, je dois les rassembler dans un même vecteur.

    @ MatRem: ((B*)Vec[0])->BB(); Merci , ça marche au poil !

    En fait, ça m'étonne à moitié, comment ça se passe quand on range un pointeur vers une classe dérivée dans un conteneur de sa base ? Il est casté ? Dans ce cas comment est-ce possible de récupérer correctment un pointeur vers la dérivée ? Bref, comment ça se passe ?

    Encore merci
    ++

  9. #9
    Membre émérite Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Par défaut
    Tes 3 classes héritent de A, c'est pour cette unique raison que tu peux les ranger dans le vecteur.

    Tu utilises bien le polymorphisme.

    Le conteneur alloue pour chaque élément la taille d'un objet de type A, plus l'espace mémoire ajouter par les classes dérivées.

    Sans cast explicite, depuis le vecteur, tu récupères un pointeur sur un objet A, mais quand tu castes en B, l'intégralité des attributs et méthodes deviennent visibles à nouveau.

    Pour faire un parallèle facile à comprendre, c'est identique à une union:
    L'espace mémoire alloué est l'espace du plus grand type.

  10. #10
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    @ d-a-v-e: Le polymorphisme ne me convient pas ici car mes classes sont trop différentes pour que je puisse regrouper leurs méthodes sous de même noms. Néanmois, je dois les rassembler dans un même vecteur.
    Dans ce cas, mauvaise conception. Oublie le fait de les ranger dans un même conteneur de A* si tu ne dois pas tous les manipuler en tant que A*.

    @ MatRem: ((B*)Vec[0])->BB(); Merci , ça marche au poil !
    Oublie ça aussi... Au pire utilise dynamic_cast, qui est le seul bon opérateur de conversion sans ce cas, mais ce ne sera pas forcément mieux. Voir la FAQ :
    http://c.developpez.com/faq/cpp/?pag...RS_downcasting

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Pour faire un parallèle facile à comprendre, c'est identique à une union:
    L'espace mémoire alloué est l'espace du plus grand type
    Non. L'espace alloué est celui d'un pointeur, qui sera le même quelque soit la classe vers laquelle on va pointer (pointeur = adresse mémoire). Par contre si on n'utilisait pas de pointeur, là seule la place pour un A serait allouée, et on perdrait allors toute donnée spécifique à B si on en copiait une instance (-> slicing).

  12. #12
    Membre émérite Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Par défaut
    Oui, le dernier paragraphe est de trop et faux.

  13. #13
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    Citation Envoyé par Fy_Hertz
    @ d-a-v-e: Le polymorphisme ne me convient pas ici car mes classes sont trop différentes pour que je puisse regrouper leurs méthodes sous de même noms. Néanmois, je dois les rassembler dans un même vecteur.
    si tu peux les faire heriter, tu peux utiliser le polymorphysme!!!
    ce n'est pas parcque toutes les classes ont les memes noms de fonctions
    qu'elles font la meme chose!!
    Citation Envoyé par Fy_Hertz
    En fait, ça m'étonne à moitié, comment ça se passe quand on range un pointeur vers une classe dérivée dans un conteneur de sa base ? Il est casté ? Dans ce cas comment est-ce possible de récupérer correctment un pointeur vers la dérivée ? Bref, comment ça se passe ?
    il n ya pas de cast!! un objet d une classe derivee est AUSSI objet de la classe base!!

    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)

  14. #14
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    si tu peux les faire heriter, tu peux utiliser le polymorphysme!!!
    ce n'est pas parcque toutes les classes ont les memes noms de fonctions
    qu'elles font la meme chose!!
    Ne pas oublier que l'héritage publique modélise à la base une relation EST-UN, et n'est pas une bidouille permettant de regrouper différentes classes dans un même conteneur... Il y a un moment où il faut revenir à la conception.

    l n ya pas de cast!! un objet d une classe derivee est AUSSI objet de la classe base!!
    Si, même s'il est automatique (il peut notamment y avoir calcul d'offset pour retrouver le pointeur sur la classe de base).
    Et on parle bien de dérivation publique, pour les autres c'est une autre histoire.

    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)
    Tu en es sûr ?

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 394
    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 394
    Par défaut
    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)
    Non, seulement si la RTTI (Run-Time Type Identification) est activée.

    En polymorphisme, le compilo ne rajoute que le pointeur vers la table des pointeurs de fonctions virtuelles de la classe. (la vtable)
    (Je le sais, j'ai eu à regarder des déclarations d'objets où la vtable devait être explicite)
    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.

  16. #16
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    Citation Envoyé par Loulou24
    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)
    Tu en es sûr ?
    je l ai lu dans le livre de Bjarne Stoustrup!!! (3 eme edition)

    si t as interesse jpourrais te donner la page exacte!

  17. #17
    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 : 50
    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
    Par défaut
    Citation Envoyé par Médinoc
    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)
    Non, seulement si la RTTI (Run-Time Type Identification) est activée.
    Si on compile sans RTTI, on ne compile pas du C++. La RTTI n'est pas optionelle en C++, elle fait partie à part entière du langage. Après, que certains compilateur décident de permettre à l'utilisateur de compiler d'autres langages que le C++ pur et dur, c'est leur problème. On peut d'ailleurs noter que dans le cas auquel tout le monde pense, le RTTI est bien devenu activé par défaut dans la dernière version, et qu'il faut une action spécifique de l'utilisateur pour le désactiver.


    Citation Envoyé par Médinoc
    En polymorphisme, le compilo ne rajoute que le pointeur vers la table des pointeurs de fonctions virtuelles de la classe. (la vtable)
    (Je le sais, j'ai eu à regarder des déclarations d'objets où la vtable devait être explicite)
    Et qui te dis que cette vtable ne contient pas aussi (ou ne peut pas aussi contenir) des informations sur le type ?
    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.

  18. #18
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    180
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 180
    Par défaut
    Citation Envoyé par JolyLoic
    Citation Envoyé par Médinoc
    pour le polymorphysme le comilateur rajoute une donnee type dans la classe base pour retrouver la classe de chaque pointeur!! (le createur du c++)
    Non, seulement si la RTTI (Run-Time Type Identification) est activée.
    Si on compile sans RTTI, on ne compile pas du C++. La RTTI n'est pas optionelle en C++, elle fait partie à part entière du langage. Après, que certains compilateur décident de permettre à l'utilisateur de compiler d'autres langages que le C++ pur et dur, c'est leur problème. On peut d'ailleurs noter que dans le cas auquel tout le monde pense, le RTTI est bien devenu activé par défaut dans la dernière version, et qu'il faut une action spécifique de l'utilisateur pour le désactiver.
    d' ailleurs, je ne voit pas comment pourrait on parler de plymorphysme sans RTTI!!! avant l execution du programme le compilateur ne sait pas quelle fonction la programme va appeler!


    je me trompe?

  19. #19
    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 : 50
    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
    Par défaut
    En général, ce qu'on entends par RTTI, ce sont dynamic_cast et typeid. Le mécanisme de virtualité est considéré comme acquis par tous.

    (la seule référence à rtti dans la norme C++ est pour décrire le header <typeinfo>, qui défini le type de ce qui est retourné par typeid, ainsi que les exceptions que dynamic_cast et typeid peuvent lancer)
    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.

  20. #20
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 16
    Par défaut
    Un grand merci à vous les gars, tout devient clair maintenant
    Je préfère tout garder dans un même vecteur mais j'ai revu ma hierarchie.

    Merci de votre aide !

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Petit Problème d'héritage?
    Par Enjaye dans le forum C++
    Réponses: 9
    Dernier message: 14/11/2012, 14h48
  2. Petit problème d'héritage
    Par ohichamo dans le forum C++
    Réponses: 3
    Dernier message: 04/07/2012, 10h21
  3. Petit problème d'héritage.
    Par tifil dans le forum C++
    Réponses: 19
    Dernier message: 08/03/2012, 18h04
  4. Petit problème d'héritage
    Par AF_2.8 dans le forum C++
    Réponses: 4
    Dernier message: 02/12/2010, 16h33
  5. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55

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