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

SL & STL C++ Discussion :

utilisation d'une list d'objet


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 65
    Par défaut utilisation d'une list d'objet
    Bonjour,

    J'ai un petit problème de compréhension avec les list.
    J'ai déclaré ma variable ainsi,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    list<Utilisateur*> listeUtilisateur;
    Ensuite je vais insérer dans ma liste via le constructeur de la classe Utilisateur, un nouvel utilisateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Utilisateur::Utilisateur():nomUtilisateur(), prenomUtilisateur(), adresse(), codePostal(), ville(), telephone()
    {
      listeUtilisateur.push_back(this);
    }
    Jusque là pas de souci.
    Je veux pouvoir supprimer un utilisateur de ma liste avec la méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Utilisateur::supprimerUtil(Utilisateur* utilASupprimer)
    {
      listeUtilisateur.erase(utilASupprimer);
    }
    Et là j'ai l'erreur:
    "no macthing function for call to ...."
    Cela viendrait apparemment d'une mauvaise utilisation des pointeurs, non?
    Quelqu'un pourrait-il me donner quelques explications ?
    Merci!

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    En fait std::list::erase fonctionne avec des itérateurs.
    Il faut utiliser std::list::remove pour faire ce que tu veux faire, cf. cette entrée de la FAQ.

    MAT.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 65
    Par défaut
    Merci de la réponse. J'avais lu beaucoup trop vite sur mon bouquin sur le coup.
    En lisant le message, j'ai même cru qu'il s'était trompé dans le livre

    Encore merci et à bientôt pour la prochaine bourde

  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
    Salut,

    Quelques petites questions et remarques cependant...

    Tu semble vouloir utiliser une liste de... pointeurs sur Utilisateur.

    Classiquement, cela implique deux possibilités:
    1. Soit, la classe Utilisateur est le type de base d'objet à vocation polymorphe
    2. Soit, tu veux manipuler des objets au sujet desquels la responsabilité de la durée de vie ne dépend pas de la liste (ou de ce qui l'utilise).


    Ce n'est qu'un détail, mais, confirmes-tu être dans une de ces situations

    Si ce n'est pas le cas, il me semble qu'il n'est pas vraiment intéressant de manipuler des pointeurs

    Tu définis un constructeur ne prenant pas d'argument pour ta classe Utilisateur.

    Cela implique que tu va devoir placer des mutateurs sur (entre autres) le nom et le prénom de cette classe.

    Si je peux concevoir qu'un utilisateur vienne à déménager ou à changer de numéro de téléphone, j'ai par contre beaucoup plus de mal à imaginer que Jean Durant finisse par s'appeler... Adèle Blancsec, (du moins, en étape de conception d'une application, car je laisse les gens libres de vivre leur vie comme ils l'entendent ) malgré les avancées de la médecine dans le domaine

    De plus, tu sera surement amené de manière très régulière à effectuer des recherches sur ces différentes données (le nom et / ou le prénoms), ce qui impliquera peut être la nécessité de trier les utilisateurs sur base de ces données, et, pourquoi pas, le besoin de recourir à des collections d'objets plus adaptées que la liste, garantissant le maintien des éléments dans un ordre particulier.

    Le problème, c'est que si tu permet la modification de ne serait-ce qu'une seul de ces deux données, tu met à mal le maintien trié de ces collections.

    Il ne me semble donc pas opportun (en vertu de la loi Demeter) de rajouter de tels mutateurs, et, par voie de conséquence, tu ne devrais pas avoir de constructeur ne prenant aucun argument, mais, bel et bien, un constructeur prenant obligatoirement au minimum le nom et le prénom, et, de manière éventuellement facultative les informations relatives à l'adresse

    Enfin, toujours d'après la loi Demeter, s'il est normal que la liste d'utilisateur ait connaissance... de la classe Utilisateur, je trouve dommage de forcer la classe Utilisateur à... avoir connaissance de la liste d'utilisateurs D'autant plus que, de toutes évidence, tu veux déclarer la liste d'utilisateurs comme... variable globale (vu que tu ne la transmet pas comme argument au constructeur de la classe Utilisateur), et que les variables globales, CEYMAL (Pour être clair, leur utilisation doit en tout état de cause être limitée au stricte minimum, et nous ne sommes vraiment pas confronté à une situation qui le justifie ici ).

    Cela nous ramène donc à ma première question (en particulier à l'aspect polymorphe éventuel de la classe Utilisateur), car la manière de travailler finale dépend fortement de la réponse que tu y aura apportée.

    En effet, si la classe Utilisateur a vocation polymorphe, il devient relativement important de faire en sorte de limiter au maximum les dépendances entre la liste d'utilisateur d'une part et les différents types qui peuvent en dériver d'autre part.

    L'idée serait donc de créer une... fabrique d'utilisateurs, qui créerait et renverrait , sur base d'un argument dont le type et les valeurs potentielles sont à déterminer, l'utilisateur du type attendu.

    La liste (ou la classe qui la gère) s'adresserait alors à cette fabrique pour obtenir chaque nouvel utilisateur à ajouter et... ajouterai l'utilisateur "fraichement créé" à la liste en question.

    Si la classe Utilisateur n'a pas vocation polymorphe et que tu laisse tomber l'utilisation d'un pointeur dans la liste, cela devient encore plus simple: il "suffit" de faire en sorte d'ajouter directement le nouvel utilisateur à la liste au moment de sa création, pas au travers du constructeur de la classe de l'utilisateur, mais bien... au travers de la fonction qui s'occupe de créer le dit utilisateur.

    Au final, nous pourrions obtenir quelque chose comme (version "polymorphe")
    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
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    class Utilisateur
    {
        public:
            Utilisateur(std::string const & n, std::string const & p):name_(n),
            firstname_(p){}
            virtual ~Utilisateur()
            /* à redéfinir pour chaque type dérivé de manière à
             * ce qu'il renvoie... le type adéquat, correctement initialisé */
            virtual Utilisateur * clone(std::string const & n, std::string const & p
                                        /* , ...*/) const = 0;
    };
    /* quelques classe dérivant de utilisateur, que je ne présente pas ici */
    /* la fabrique */
    /* on pourrait envisager l'utilisation d'un singleton, mais, de toute évidence,
     * cette fabrique ne sera utilisée... qu'à certains point bien précis.
     * Le singleton ne se justifie donc pas vraiment ;)
     */
    class Fabrique
    {
        public:
           /* une possibilité parmi d'autres pour déterminer le type 
            * d'utilisateur que l'on veut obtenir
            */
           enum enumType{typeUtilisateur1,
                typeUtilisateur2,
                typeUtilisateur3};
           Fabrique()
           {
               /* on enregistre tous les types envisagés */
               items_.insert(std::make_pair(typeUtilisateur1,new TypeDerive1("",""));
               items_.insert(std::make_pair(typeUtilisateur2,new TypeDerive2("",""));
               items_.insert(std::make_pair(typeUtilisateur3,new TypeDerive3("",""));
           }
           /*!!! il n'apparait pas ici, mais il faut veiller à ce que le destructeur
            * libère correctement la mémire lors de la destruction de la fabrique ;)
            */
           Utilisateur * create(Fabrique::enumType t, std::string const &p,
                                std::string const & f) const
           {
               std::map<enumType, Utilisateur *>::const_iterator it=items_.find(t);
               return (it==items_.end() ? NULL : it->second->clone(p,f);
           }
    };
    void foo()
    {
        /* la liste d'utilisateurs :D */
        std::list<Utilisateur *> l;
        std::string n;
        std::string p;
        Utilisateur::enumType t;
        Fabrique f;
        /* récupération des données nécessaires à la création d'un utilisateur
         * particulier, et... du type d'utilisateur attendu 
         */
        l.push_back(f.create(t,p, n));
        /* utilisation de l */
        /* faudra pas oublier de libérer correctement la mémoire allouée à 
         * chacun des léments de la liste ;)
         */
    }
    S'il la classe Utilisateur n'a pas vocation polymorphe, et qu'elle ne l'aura jamais, le tout pourrait être simplifié (pense à inclure le fichier d'en-tête dans lequel la classe Utilisateur est définie) en quelque chose comme
    void foo()
    {
    std::list<Utilisateur> l;
    std::string n;
    std::string p;
    /* récupération des données nécessaires à la création d'un utilisateur
    * particulier, et... du type d'utilisateur attendu
    */
    l.push_back(Utilisateur(p, n));
    /* utilisation de l */
    }
    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. creer et utiliser une liste d'objets (TObjectList)
    Par Babylonne dans le forum C++Builder
    Réponses: 4
    Dernier message: 08/11/2007, 23h27
  2. Créer une liste d'objets statiques dans une classe
    Par crossbowman dans le forum C++
    Réponses: 3
    Dernier message: 13/03/2006, 09h11
  3. methode qui retourne une liste d'objets du meme type
    Par anoukhan dans le forum Oracle
    Réponses: 8
    Dernier message: 12/01/2006, 18h38
  4. Tri d'une liste d'objet CObList
    Par cjacquel dans le forum MFC
    Réponses: 1
    Dernier message: 13/07/2005, 13h50
  5. [MFC] Retourner une liste d'objets
    Par 1cado dans le forum MFC
    Réponses: 10
    Dernier message: 28/07/2003, 12h11

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