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

Langage C++ Discussion :

downcast et liste d'instances


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2009
    Messages : 42
    Par défaut downcast et liste d'instances
    Bonjour,

    j'ai une classe mere avec une fonction virtuelle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class A{
    protected:
       unsigned int m_type;
     
    public:
       A();
       virtual ~A();
       virtual bool do();
    };
    et des classes filles Aa et Ab qui implementent la methode do().

    je souhaite avoir une liste vector<A*> myList et pouvoir iterer de maniere à appeler la bonne methode do() en fonction de la fille ( *it->do() ), tout en restant générique. Or j'ai lu (et testé) que le downcast en C++ n'etait pas safe (contrairement à Java).

    Alors, je ne vois pas comment procéder. Avez-vous des conseils à me donner?

    Merci de votre aide

  2. #2
    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
    La fonction do() est virtuelle, donc tu as déjà le comportement que tu veux.
    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 émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    En effet, aucun cast dans le code que tu montre.

    Un downcast serait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Aa* aa = (Aa*)a; // Non safe
    Aa* aa = dynamic_cast<Aa*>(a); // Safe

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2009
    Messages : 42
    Par défaut manque de clarté desolée
    je m'explique donc:

    dans mon main j'instancie un Aa* pAa et un Ab* pAb, chacun ayant sont m_type à 0 et 1 respectivement (via un enum).

    Par la suite je les "push" dans la liste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    myList.push_back(dynamic_cast<A*>(pAa));
    myList.push_back(dynamic_cast<A*>(pAb));
    Or myList[0]->do() appelle la declaration dans la classe mère et non celle de la fille.

  5. #5
    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
    Euh, mais tu n'as même pas à faire de dynamic_cast, ici...

    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
    #include<iostream>
    #include <list>
     
    class A{
     
    public:
       A() {}
       virtual ~A() {}
       virtual void do() { std::cout<< "A" << std::endl; }
    };
     
    class Aa : public A {
     
    public:
       Aa() {}
       virtual ~Aa() {}
       virtual void do() { std::cout<< "Aa" << std::endl; }
    };
     
    class Ab : public A {
     
    public:
       Ab() {}
       virtual ~Ab() {}
       virtual void do() { std::cout<< "Ab" << std::endl; }
    };
     
    void TestHeritage(void)
    {
      std::list< A* > myList;
      myList.push_back(new Aa);
      myList.push_back(new Ab);
     
      for(std::list< A* >::iterator it=myList.begin ; it!=myList.end() ; ++it)
      {
        (*it)->do();
      }
    }
    Ceci, si ça compile, devrait donner le bon comportement.
    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.

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

    Informations professionnelles :
    Activité : aucun

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

    Pour te permettre de comprendre...

    Si tu as une hiérarchie de classes proche de
    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
    class A
    {
        public:
            virtual ~a(); //nécessaire si tu veux pouvoir détruire tes objets
                          // dérivés au départ des pointeurs sur A
            virtual bool do();
        /*tout le reste */
    };
    class B : public A
    {
        /*les trucs adaptés pour B */
    };
    class C : public A
    {
        /* les trucs adaptés pour C */
    };
    Tu dispose, du fait de l'héritage, d'une relation EST-UN pour tes classe B et C.

    En effet, B EST-UN A et on peut en dire autant de la part de C.

    De ce fait, n'importe quel B ou n'importe quel C peut parfaitement passer pour un A, bien qu'il souffre de la restriction que tu ne puisse appeler que les fonctions déclarées dans A.

    Si donc, tu crées des B et des C et que tu les places dans une collection de pointeurs de type A, tu pourra sans problème invoquer la fonction do depuis n'importe quel élément de la dite collection.

    Comme la fonction do est déclarée virtuelle, son comportement sera adapté au type dynamique de l'objet, si elle est redéfinie dans une des classes enfant de A.

    C'est ca ce que l'on appelle le polymorphisme (enfin, l'un des polymorphismes possibles en C++)

    Il n'y aura que si tu veux, en partant de ta collection de pointeurs sur des objets de type A, pouvoir appeler des comportements spécifiques au B ou au C que tu devra envisager le downcasting.

    Dans ce cas, il vaut mieux privilégier un transtypage "sécurisant" tel que dynamic_cast ou static_cast par rapport à un transtypage sauvage "a la C"
    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

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2009
    Messages : 42
    Par défaut j'ai compris...
    je ne dois pas faire de cast justement!

    Exemple:
    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
     
    #include <string>
    #include <iostream>
    #include <vector>
    using namespace std;
     
    class Chumain{
    protected:
    	std::string m_Genre;
    public:
    	Chumain(){};
    	virtual ~Chumain(){};
    	virtual void jesuis(){cout<<"je suis un humain"<<endl;};
    };
     
    class Cfemme: public Chumain{
    public:
    	Cfemme(){};
    	virtual ~Cfemme(){};
    	void jesuis(){cout<<"je suis une femme"<<endl;};
    };
     
    class Chomme: public Chumain{
    public:
    	Chomme(){};
    	virtual ~Chomme(){};
    	void jesuis(){cout<<"je suis un homme"<<endl;};
    };
     
     
     
    int main() {
    	Cfemme* sophie = new Cfemme();
    	Chomme* vincent = new Chomme();
     
    	std::vector<Chumain*> mesHumains;
    	mesHumains.push_back(sophie);
    	mesHumains.push_back(vincent);
     
    	for (std::vector<Chumain*>::iterator it = mesHumains.begin(); it != mesHumains.end(); it++) {
    		(*it)->jesuis();
    	}
    	return 0;
    }
    au run, on a les traces suivantes:
    je suis une femme
    je suis un homme
    Merci

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par zerbynette Voir le message
    je ne dois pas faire de cast justement!
    Ben oui, c'est bien ce que je t'expliquais...

    Ici, tu laisse simplement agir le polymorphisme

    il n'y a que si tu veux récupérer, selon ton exemple, un objet de type CFemme pour le premier élément de ta liste (parce que tu veux appeler, par exemple, la fonction membre tricoter, qui n'existe (soyons machos ) que pour la classe CFemme ) que tu devra recourir au transtypage
    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

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

Discussions similaires

  1. Liste des instances d'une classe
    Par alexdevl dans le forum Général Python
    Réponses: 32
    Dernier message: 14/09/2011, 22h52
  2. Trier une liste d'instance avec sort()
    Par Yachas dans le forum Général Python
    Réponses: 7
    Dernier message: 10/02/2011, 03h31
  3. Liste les instances d'une classe
    Par Mucho dans le forum Langage
    Réponses: 2
    Dernier message: 12/09/2009, 17h24
  4. STL Problème avec une liste d'instances de class
    Par BruceBoc dans le forum SL & STL
    Réponses: 12
    Dernier message: 16/02/2007, 14h12
  5. liste des instances
    Par exyacc dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 30/06/2006, 11h18

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