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++

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

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    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 sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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 du Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    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 sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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 éprouvé
    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
    Points : 1 060
    Points
    1 060
    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 sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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 éprouvé
    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
    Points : 1 060
    Points
    1 060
    Par défaut
    Ok, merci pour les précisions.

  8. #8
    Membre habitué Avatar de zhouyu
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 90
    Points : 143
    Points
    143
    Par défaut
    Salut.
    Je ne vois pas l’intérêt d'utiliser le polymorphisme si au final on doit récupérer le type de l'objet ?
    Pour ma part j'ai généralement une méthode commune qui est adapté en fonction de la classe enfant et qu'on appellera par la suite.
    C'est pour moi la force d'utiliser le polymorphisme, peu importe la classe qu'on passe le traitement est adapté.

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par zhouyu Voir le message
    Salut.
    Je ne vois pas l’intérêt d'utiliser le polymorphisme si au final on doit récupérer le type de l'objet ?
    Pour ma part j'ai généralement une méthode commune qui est adapté en fonction de la classe enfant et qu'on appellera par la suite.
    C'est pour moi la force d'utiliser le polymorphisme, peu importe la classe qu'on passe le traitement est adapté.
    Il y a des cas où tu n'as simplement pas le choix... :

    Le polymorphisme te permet de travailler avec "n'importe quel type d'objet dérivé" comme s'il "s'agissait d'objet du type de base".

    Tu peux donc, grâce à l'héritage et au polymorphisme, travailler avec des vélos, des voitures, des bateau et des avions mélangés dans une même collection de (pointeur sur) véhicules, mais, tu ne les connais que comme étant... des véhicules.

    C'est très bien, mais jusqu'à un certain point seulement, dans le sens où il y aura fatalement un moment où, même si tu pars du principe qu'il s'agit d'un véhicule, tu devras prendre en compte le fait qu'il s'agit d'un type spécifique de véhicule pour certains services qu'ils doivent rendre.

    Il faut donc régulièrement que tu sois en mesure de savoir si tu travailles avec des patins à roulettes ou avec des avions, alors que tu connait l'un et l'autre comme étant des véhicules.

    Le seul moyen d'y arriver passe 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

  10. #10
    Membre habitué Avatar de zhouyu
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2009
    Messages : 90
    Points : 143
    Points
    143
    Par défaut
    Merci pour la réponse

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

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    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 ;

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lolaalol Voir le message
    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 ;
    oui, tout à fait, à condition bien sur que tu puisses disposer des pointeurs intelligents, soit parce que tu peux compiler en mode "C++11", soit parce que tu peux utiliser boost

    Cependant, je me tournerais peut etre plus volontiers vers un unique_ptr que vers un shared_ptr, mais il me manque peut-être des informations pour décider en connaissance de cause
    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

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

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    Par défaut
    Citation Envoyé par koala01 Voir le message
    oui, tout à fait, à condition bien sur que tu puisses disposer des pointeurs intelligents, soit parce que tu peux compiler en mode "C++11", soit parce que tu peux utiliser boost

    Cependant, je me tournerais peut etre plus volontiers vers un unique_ptr que vers un shared_ptr, mais il me manque peut-être des informations pour décider en connaissance de cause
    Merci pour votre aide.

    Voici un lien vers un "article" (sur le site d'un de mes anciens professeurs), a propos des pointeurs intelligents. http://h-deb.clg.qc.ca/Sujets/AuSeco...elligents.html

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lolaalol Voir le message
    Merci pour votre aide.

    Voici un lien vers un "article" (sur le site d'un de mes anciens professeurs), a propos des pointeurs intelligents. http://h-deb.clg.qc.ca/Sujets/AuSeco...elligents.html
    Cet article est particulièrement instructif, et correspond, de manière générale, à ce que l'on essaye d'inculquer sur le forum.

    Cependant, j'ai l'impression que cet article fait la part un peu trop belle à shared_ptr et à auto_ptr à mon gout.

    En effet, ce n'est pas pour rien que auto_ptr a été déprécié en C++11, car il n'est vraiment pas en odeur de sainteté (une recherche sur le forum te donnera surement les raisons de ce fait ) et shared_ptr n'est intéressant que lorsque tu as effectivement besoin de pointeurs partagés.

    C'est pour cela que je te conseille, si tu n'a pas la possibilité de profiter des nouvelles fonctionnalités apportées par C++11, de t'intéresser un d'un peu plus près à boost et aux smart pointers que cette bibliothèque propose et, si tu peux disposer des fonctionnalités apportées par C++11 de t'interroger sur l'éventualité d'utiliser des unique_ptr par exemple.

    Mais comme un conseil seul ne vaut rien, je vais me fendre de quelques raisons pour le justifier à tes yeux

    Si je te conseille fortement de t'orienter vers les pointeurs intelligents de boost si tu ne disposes pas des fonctionnalités de C++11, c'est parce que:
    • boost est un ensemble de bibliothèques dont une bonne partie préfigure ce qui a été inclus dans C++11 ou qui a de bonne chances d'être inclus dans les normes suivantes
    • boost est un ensemble de bibliothèques très largement reconnues et fortement utilisées, ce qui te garanti une très bonne stabilité à l'utilisation
    Si j'insiste sur le fait que tu devrais également envisager l'utilisation de unique_ptr si tu disposes de la possibilité de recourir aux fonctionnalités de C++11, c'est essentiellement pour t'inciter à réfléchir "en profondeur" à la question "qui est responsable des pointeurs" et surtout à la question de savoir "comment seront utilisés tes pointeur".

    Je ne dis pas que le choix d'un shared_ptr est mauvais en soi, je dis "simplement" que la réflexion pourrait t'amener à envisager une solution éventuellement meilleure.

    Je ne serais pas étonné outre mesure qu'un unique_ptr puisse trouver grâce à tes yeux même si je n'ai, il faut bien l'avouer, qu'une connaissance vraiment partielle de ton projet

    Ce qui importe dans tout cela, c'est que tu ne te jettes pas sur la première solution qui se présente, mais que tu fasses un choix en connaissance de cause car le choix que tu t'apprêtes à faire est, clairement, de nature à avoir des répercussions importantes sur toute la suite de ton projet.

    Alors, peut etre que la réflexion te mènera effectivement à la conclusion que tu as bel et bien besoin d'un shared_ptr, et ce sera tant mieux pour toi

    Mais il serait dommage de se refuser cinq minutes de réflexion pour se rendre compte, plus tard, avec l'évolution des besoin et donc l'augmentation de la complexité de ton projet, que tu aurais sans doute eu avantage à utiliser un unique_ptr (ou n'importe quel pointeur intelligent dont tu aurais pu disposer)
    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

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

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    Par défaut
    Il m'est impossible de faire cela :
    EDIT : ceci était une erreur du à ma méthod virtuelle que javais définit comme étant constante ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    liste<unique_ptr<Probleme*>> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- error : objet de type classe abstraite "Maladie" non autorisé
    Autre truc que je ne comprend pas vraiment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    list<Probleme*> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- pas d'erreur
    liste<unique_ptr<Probleme*>> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- erreur de constructeur : aucun constructeur pour la conversion de Maladie * en unique_ptr

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lolaalol Voir le message
    Il m'est impossible de faire cela :
    EDIT : ceci était une erreur du à ma méthod virtuelle que javais définit comme étant constante ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    liste<unique_ptr<Probleme*>> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- error : objet de type classe abstraite "Maladie" non autorisé
    S'il te dit que Maladie est une classe abstraite, c'est très certainement parce qu'il reste une fonction virtuelle pure pour laquelle tu n'as pas fournit d'implémentation dans maladie...

    Ton compilateur devrait d'ailleurs t'indiquer un peu plus loin la fonction qui est encore virtuelle pure

    Ceci dit, je suis étonné des noms "liste" et de "InsérerAlaFin"...tu devrais regarder plutôt soit du coté de std::list soit du coté de std::vector
    Autre truc que je ne comprend pas vraiment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    list<Probleme*> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- pas d'erreur
    liste<unique_ptr<Probleme*>> ListeDeProbleme;
    ListeDeProbleme.InsererAlaFin(new Maladie(mes params...)); <- erreur de constructeur : aucun constructeur pour la conversion de Maladie * en unique_ptr
    Et pour cause, dans le deuxième cas, tu essayes d'insérer un pointeur de type problème alors que tu devrais insérer un objet de type unique_ptr<Probleme>...

    L'instruction qu'il te faut est plutôt proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::list<std::unique_ptr<Probleme>> listeDeProblemes;
    listeDeProblemes.push_back(std::unique_ptr<Probleme>(new Maladie(/*argiuments */ ) ));
    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

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

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 45
    Points
    45
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ceci dit, je suis étonné des noms "liste" et de "InsérerAlaFin"...tu devrais regarder plutôt soit du coté de std::list soit du coté de std::vector
    C'est ma propre class liste et quand j'ai fais cela mon professeur ne voulais pas de nom en anglais ^^. je me suis tourné vers la list STL pour avoir moin de problème.

    Comment je dois faire pour supprimer manuellement mes unique_ptr, car dans mon programme à chaque fois que je reviens au menu principale je dois supprimer mes listes. Es qu'il faut supprimer les elements de la liste avant les pointeurs ou l'inverse ?

    genre :
    list.clear();
    delete pointer;

  18. #18
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    le but des pointeurs intelligents est, justement, de le rendre responsable de la durée de vie des pointeurs, en fonction du type de pointeur intelligent utilisé

    std::unique_ptr par exemple représente un pointeur qui n'est pas partagé entre différentes classes.

    Lorsque l'objet auquel il appartient est détruit, ou que l'on atteint la fin de la portée dans laquelle il est déclaré, la mémoire allouée au pointeur est correctement libérée de manière automatique:
    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 MachinTruc
    {
        public:
            MachinTruc():ptr(new Bidule){}
        /* ...*/
        private:
        std::unique_ptr<Bidule> ptr;
    }
    int main()
    {
        MachinTruc obj;
        std::unique_ptr<UnType> one(new UnType);
        if(test)
        {
            std::unique_ptr<AutreType> two(new AutreType);
            /* ce qui suit n'est peut etre pas très efficace du point de vue des 
             * performances, mais
             */
           for(int i=0;i<10:++i)
           {
                 std::unique_ptr<AutreType> three(new AutreType);
                 /* ... */
           } // libération de la mémoire allouée à three ici
            /* ... */
        }// libération de la mémoire allouée à two ici
         /* ... */
         return 0;
    } // libération de la mémoire allouée à one ici
       // obj est détruit : libération de la mémoire allouée à objet.ptr ici
    std::shared_ptr est quant à lui un pointeur intelligent qui dispose d'un comptage de référence. La mémoire qui lui est allouée est automatiquement libérée lorsque le compteur de référence revient à 0.

    Enfin std::weak_ptr représente un pointeur qui peut être invalidé, par exemple, si le compteur de référence du std::shared_ptr responsable de la durée de vie de la valeur pointée atteint 0.

    Lorsque tu mets un pointeur intelligent dans une collection, tu travailles avec ce pointeur intelligent exactement comme s'il s'agissait d'une valeur quelconque: en retirant un élément de la collection, tu détruit cet élément, et la mémoire allouée à la valeur pointée est libérée "si nécessaire" (comprend : automatiquement s'il s'agit d'un std::unique_ptr, en fonction du comptage de référence s'il s'agit dun std::shared_ptr)

    Du moment que tu sais à comment ton pointeur sera utilisé, le pointeur intelligent s'occupera du reste pour déterminer s'il faut libérer la mémoire allouée à l'objet pointé ou non
    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

  19. #19
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lolaalol Voir le message
    C'est ma propre class liste et quand j'ai fais cela mon professeur ne voulais pas de nom en anglais ^^
    A titre perso, je trouve que c'est un bel imbécile...

    Les noms anglais sont souvent beaucoup plus simple que leur équivalent français (push_back contre insertAlaFin, y a pas photo hein ) mais, en plus, l'informatique est, typiquement, un domaine fortement internationalisé dans lequel on mérite de se faire comprendre du plus grand nombre.

    L'anglais est la lange idéal pour remplir cet objectif
    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

  20. #20
    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 koala01 Voir le message
    Les noms anglais sont souvent beaucoup plus simple que leur équivalent français (push_back contre insertAlaFin, y a pas photo hein )
    Sauf que push_back est aussi anglais que pousse_queue est français, et là la différence est plus mineure... Même si elle te saute aux yeux par l'habitude que tu as de la langue française.

    Maintenant, je suis d'accord que insertAlaFin n'est pas terrible, mais insèreÀLaFin est déjà plus correct, ou ajouteEnQueue.
    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.

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