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 :

Liste et classe abstraite


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut Liste et classe abstraite
    Bonjour Tout le monde !

    J'ai une class abstraite "Probleme" et à deux enfants "Maladie" et "Blessure"

    Mon probleme est que je dois faire une liste de "Probleme" mais je ne peux pas instancier une classe abstraite dans ma liste donc comment faire ma liste ?

  2. #2
    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,

    Tu dois créer une liste de pointeurs (de préférence intelligents) sur problème et y placer des pointeurs (de préférence intelligents) sur maladie ou sur blessure.

    Soit toutefois attentif au fait que, une fois qu'il seront placés dans ta liste, tes différents problèmes seront connus comme... des problèmes.

    Tu ne pourras donc plus envisager "sereinement" d'y accéder que comme s'il s'agissait de problème, sans précision.

    Si tu te trouves face à une situation qui nécessite de savoir précisément si tu as affaire à une blessure ou à une maladie, il faudra, fatalement, passer par le double dispatch
    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

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    Justement, Problème est une classe virtuelle pure pour que je puisse utiliser le polymorphisme, je dois pouvoir faire sa genre
    : Leproblem->QuelEstTonProbleme()

    et cela me sort la blessure ou la maladie.

    Qu'es que tu veux dire par double dispatch ?

  4. #4
    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 lolaalol Voir le message
    Justement, Problème est une classe virtuelle pure
    Non...

    Ce n'est qu'une question de termes, mais bons, ils sont importants

    Virtuelle pure, cela s'applique à certaines fonctions lorsqu'on ne donne strictement aucun comportement, à charge pour la classe dérivée de fournir le comportement qui va bien.

    Une classe qui contient au moins une fonction virtuelle pure (qu'elles soit déclarée dans sa propre interface ou qu'elle soit héritée mais non définie depuis une de ses classes ancêtre) s'appelle une classe abstraite

    Problème est donc une classe abstraite parce que je présume que QuelEstLeProblème est une fonction virtuelle pure dans Problème

    Là, les termes sont bons

    pour que je puisse utiliser le polymorphisme, je dois pouvoir faire sa genre
    : Leproblem->QuelEstTonProbleme()

    et cela me sort la blessure ou la maladie.
    C'est très bien comme cela
    Qu'es que tu veux dire par double dispatch ?
    En fait, le double dispatch est une manière de travailler, basée sur le polymorphisme, qui permet de récupérer le type réel (dans le cas présent une maladie ou une blessure) au départ d'un objet passant pour être du type parent (ici un problème).

    On appelle une fonction virtuelle disponible dans la classe mère et on la redéfini dans la classe enfant pour qu'elle transmette elle-même l'objet auquel elle appartient à un autre objet (ou une autre fonction).

    Ainsi, la fonction qui est réellement appelée sait qu'elle travaille avec une blessure ou une maladie (selon ton exemple).

    Il existe le patron de conception visiteur qui est un des exemples les plus courent de double dispatch (parmi ceux dont on entend régulièrement parler du moins )

    On parle de double dispatch "simplement" parce que tu appelle une fonction qui en appelle une autre et que c'est cette deuxième fonction qui sera réellement effective
    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

  5. #5
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Citation Envoyé par koala01 Voir le message
    En fait, le double dispatch est une manière de travaillée, basée sur le polymorphisme, qui permet de récupérer le type réel (dans le cas présent une maladie ou une blessure) au départ d'un objet passant pour être du type parent (ici un problème).
    Heu, à le lire comme ça, j'ai l'impression qu'il y a méprise sur le double dispatching. C'est bien ça que tu entends?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class ClassAbstraite {
    public:
            virtual ~ClassAbstraite() ;
     
            // double dispatching par méthode (switch dans classe dérivée)
    	virtual void doubleDispathMethod( const ClassAbstraite & other ) = 0 ;
    };
     
    // double dispatching par fonction libre (switch/downcast imbriqués)
    void calculer( const ClassAbstraite & a, const ClassAbstraite & b ) ;
    Dans ce cas là, c'est une espèce assez rare de visiteurs ("binary visitor").

    Là je ne vois que du visiteur classique ou de la méthode virtuelle "classique" dans son cas et j'ai l'impression qu'il a tout simplement essayé de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::list< Probleme > problemes ;
    Comment s'en sortir : Avec des pointeurs que tu auras la charge de détruire (la liste ne fera pas delete).

    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
     
    std::list< Probleme* > problemes ;
    problemes.insert( new Maladie() );
    problemes.insert( new Blessure() );
     
    /*
     En principe, on planque ça dans le destructeur d'un objet à soit qui gère et construit les 
     problèmes
    */
    for ( std::list< Probleme* >::iterator it = problemes.begin(); it != problemes.end(); ++it ){
          it->afficheDiagnostique() ;
    }
     
     
    /*
     En principe, on planque ça dans le destructeur d'un objet à soit qui gère et construit les 
     problèmes
    */
    for ( std::list< Probleme* >::iterator it = problemes.begin(); it != problemes.end(); ++it ){
         delete *it ;
         *it = NULL ;
    }
    problemes.clear();
    C'est bien ce qui te bloquait?

    PS :
    - Il existe d'autres techniques plus propre pour ce genre de chose (boost::ptr_container, boost::variant,...)
    - Je me demande si tu ne t'embrouille pas entre l'appel de méthode virtuelle (interface de la classe abstraite) et le downcast (dynamic_cast pour accéder à des spécificités de la classe dérivée non présente sur l'interface)

  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
    Citation Envoyé par bretus Voir le message
    Heu, à le lire comme ça, j'ai l'impression qu'il y a méprise sur le double dispatching. C'est bien ça que tu entends?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class ClassAbstraite {
    public:
            virtual ~ClassAbstraite() ;
     
            // double dispatching par méthode (switch dans classe dérivée)
    	virtual void doubleDispathMethod( const ClassAbstraite & other ) = 0 ;
    };
     
    // double dispatching par fonction libre (switch/downcast imbriqués)
    void calculer( const ClassAbstraite & a, const ClassAbstraite & b ) ;
    Non, tu n'as pas compris ce que j'expliquais...

    J'ai dit que tu appelais depuis le ton objet passant pour être du type de base une fonction virtuelle de cet objet et que la redéfinition de cette fonction appelait une autre fonction en transmettant le type réel de l'objet.

    C'est à dire
    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
    /* une fonction qui sait travailler sur une blessure */
    void foo(Blessure const & b)
    {
        /* ... */
    }
    /* et une qui sait travailler sur une maladie 
     * (ca pourrait etre un nom de fonction différent)
     */
    void foo(Maladie const & m)
    {
        /* ... */
    }
    class Probleme
    {
        public:
            /* une fonction qui peut etre appelée depuis "n'importe quel problème"
             */
           virtual void do() /*const */ = 0;
    };
    class Maladie : public Probleme
    {
        public:
            /* spécialisée pour une maladie la fonction ressemble à */
            virtual void do() /*const */{ foo(*this); }
    };
     
    class Blessure : public Probleme
    {
        public:
            /* spécialisée pour une blessure, la fonction ressemble à */
            virtual void do() /* const */{ foo(*this); }
    };
    int main()
    {
        /* que ce soit une maladie */
        Problem * ptrM = new Maladie;
        /* ou une blessure */
        Problem * ptrB = new Blessure;
        /* on peut appeler do pour les deux, et chaque implémentation
         * profite du double dispatch (deux appels de fonctions qui font qu'on
         * a récupéré le type réel de l'objet sur lequel on a appelé la première)
         */
        ptrM->do();
        ptrB->do();
        /* ... */
        delete ptrM;
        delete ptrB;
        return 0; 
    }
    Voilà ce qu'est le double dispatch

    Maintenant, si, au lieu d'avoir deux fonctions libres, il s'agissait de deux surcharge d'une même fonction membre, nous aurions affaire au patron de conception "visiteur"
    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 confirmé
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    Citation Envoyé par bretus Voir le message

    Comment s'en sortir : Avec des pointeurs que tu auras la charge de détruire (la liste ne fera pas delete).

    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
     
    std::list< Probleme* > problemes ;
    problemes.insert( new Maladie() );
    problemes.insert( new Blessure() );
     
    /*
     En principe, on planque ça dans le destructeur d'un objet à soit qui gère et construit les 
     problèmes
    */
    for ( std::list< Probleme* >::iterator it = problemes.begin(); it != problemes.end(); ++it ){
          it->afficheDiagnostique() ;
    }
     
     
    /*
     En principe, on planque ça dans le destructeur d'un objet à soit qui gère et construit les 
     problèmes
    */
    for ( std::list< Probleme* >::iterator it = problemes.begin(); it != problemes.end(); ++it ){
         delete *it ;
         *it = NULL ;
    }
    problemes.clear();
    Es qu'on pourrait utiliser des pointeurs intelligents à la place, comme sa j'aurais pas besoin de les détruires moi même ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    list< shared_ptr<Probleme> > problemes ;

Discussions similaires

  1. Réponses: 2
    Dernier message: 29/10/2014, 17h10
  2. Réponses: 2
    Dernier message: 30/12/2009, 20h44
  3. [Debutant][Conception] Classes abstraites et interface.
    Par SirDarken dans le forum Langage
    Réponses: 4
    Dernier message: 29/10/2004, 00h02
  4. Classe abstraite / MVC
    Par caramel dans le forum MVC
    Réponses: 5
    Dernier message: 01/04/2003, 09h27
  5. pb constructeurs classes dérivant classe abstraite
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2003, 19h02

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