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 :

Problème avec l'usage d'une multimap


Sujet :

SL & STL C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 9
    Points : 3
    Points
    3
    Par défaut Problème avec l'usage d'une multimap
    Bonsoir,

    Nous utilisons un programme ayant recours à une multimap utilisant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    multimap<string, class Client> m;
    en clé: le champ nom d'une classe Client, et en objet: Client.

    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
     
    class Client
    {
     private:
             int m_id;
             string m_nom;
             string m_prenom;
             Adresse *m_adress;
     
     public:
             void afficher(std::ostream &out);      
             Client();
             ~Client();
             string getnom();
             string getprenom();
             Adresse* getadress();
             void setnom(string);
             void setprenom(string);
             void setadress(Adresse*);
             Client nouveauclient();
             Client &operator=(const Client &);
             //acheter();
             //avis();       
    };
    Nous avons crée une fonction devant permettre la création d'un nouveau client via la saisie de l'utilisateur.

    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
     Client Client :: nouveauclient()
    {               
          Client nouveau;
          int num,cp;
          char nom2[200],prenom2[200],rue2[400],ville2[200];          
          string rue,ville;              
     
     
     
     
                    cout << "veuillez saisir votre nom : " <<endl;
                    fflush(stdin);
                    gets(nom2);
     
     
                    cout << "veuillez saisir votre prenom : " <<endl;
                    fflush(stdin);
                    gets(prenom2);
     
                    cout << "veuillez saisir votre numero d'adresse : " <<endl;
                    cin>>num;
     
                    cout<< "Veuillez saisir votre rue : "<<endl;
                    fflush(stdin);
                    gets(rue2);
     
                    cout << "Veuillez saisir votre ville : "<<endl;
                    fflush(stdin);
                    gets(ville2);
     
                    cout << "veuillez saisir votre code postal : " <<endl;
                    cin>>cp;
     
                    nouveau.setnom(nom2);
                    nouveau.setprenom(prenom2);
                    rue=rue2;
                    ville=ville2;
     
     
                    nouveau.getadress()->setnum(num);
                    nouveau.getadress()->setville(ville);
                    nouveau.getadress()->setrue(rue);
                    nouveau.getadress()->setcp(cp);
     
     
         return nouveau;
    }
    Le retour de cette fonction est affecté dans le main à une variable de type Client:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     clien=clien.nouveauclient();
    Ce nouveau client nous essayons de l'insérer dans la multimap de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m.insert(make_pair(clien.getnom(),clien));
    Mais une fois cette insertion effectué, l'affichage du contenu de la multimap fais planter le programme.

    Le seul moyen de réussir à afficher le contenu de la multimap est de changer l'objet en l'établissant comme pointeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    multimap<string, class Client*> m;
    Ainsi que l'insertion :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m.insert(make_pair(clien.getnom(),&clien));
    Et l'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     for ( it=m.begin() ; it != m.end(); it++ )
    cout << "Clef : " << (*it).first << endl << "Client :" << *(*it).second << endl;
    Mais le problème devient que le contenu de la multimap ne change pas pour ce qui est de la donnée, la clé change mais l'objet affiché correspond au dernier client saisi.

    Merci d'avance pour votre aide, qui nous serait très précieuse!!

  2. #2
    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
    Pour fermer la balise code, c'est [/code] et non [\code]

    Pour mettre des objets dans un conteneur de la STL, ils doivent être copiables. Est-ce le cas de Client ? En particulier, Client contient un pointeur, que se passe-t-il sur le donnée pointée quand on copie un Client ?
    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.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Merci pour le coup de la balise ..

    Oui le champ m_adresse est effectivement un pointeur, mais on a surchargé l'opérateur = de la façon suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Adresse &Adresse::operator=(const Adresse &source)
    {
        m_numero = source.m_numero;
        m_CP = source.m_CP;
        m_rue = source.m_rue;
        m_ville= source.m_ville;
        return *this;
    }

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Points : 31
    Points
    31
    Par défaut
    Bonjour,

    Le fait que la classe Client créé un Client me choque, je verrai bien la fonction nouveauclient() au moins en statique. N'y a t-il pas un gestionnaire de client pour pourrait les créer ?

    Bon mais le problème ne vient certainement pas de là.

    Tu as surchargé l'opérateur = sur Adresse, mais le problème à mon avis c'est l'adresse de l'Adresse (enfin le pointeur de l'adresse).

    Je suppose que le destructeur de Client fait un delete de l'adresse (enfin il devrait puisque si on détruit un client, il faut libérer la mémoire prise par l'adresse)...

    Si je ne me trompe pas, la fonction nouveauclient() créé un Client et le renvoie par copie ! Le pointeur est donc copié aussi, mais comme le Client DANS la fonction est supprimé à la sortie de la fonction, le pointeur pointe donc dans le vide, et ça crash.

    C'est une supposition...

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    On va regarder ça!!Merci beaucoup de ta réponse!

    Par contre quand tu parles de gestionnaire de clients, je sais pas si je te suis?! A ton avis et très brièvement (on voudrait pas abuser de ta gentillesse), comment on pourrait gérer plus intelligemment la saisie des clients?

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Points : 31
    Points
    31
    Par défaut
    Par "gestionnaire de client", je parle par exemple d'une classe "Agenda" qui créerait les objets Client. En fait, la classe Client actuelle me parait avoir un défaut car si tu créé un Client, il peut de lui mettre créé autant de Clients qu'il veut, ce qui me parait un peu bizarre au point de vue conceptuel.

    Sinon pour ta fonction nouveauclient, essayes de renvoyer par valeur ou par pointeur, et de surcharger l'opérateur = aussi dans Client en recréant une Adresse avec son propre pointeur et en mettant ensuite grâce à ton opérateur = d'Adresse les données dans la nouvelle Adresse par copie comme tu as fait.

    Tiens nous au courant et bon courage

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Cela a parfaitement résolu le problème!!
    Merci beaucoup pour ton aide ..
    Cependant, je ne parviens pas à comprendre pourquoi le fait de ne pas renvoyer un pointeur vers Client posait problème :S! Puisque le destructeur du Client de la fonction est appelé à l'issue de son affectation en sortie dans le main. Logiquement, cela ne devrait pas affecter le "clien" du main. Pourrais-tu m'expliquer?

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Points : 31
    Points
    31
    Par défaut
    Bonjour,

    En fait le problème provient principalement du retour de ta fonction nouveauclient().

    Dans cette fonction, tu créé un client en faisant :
    Client nouveau;

    En sortie de la fonction, tu renvoies ce nouveau client en faisant :
    return nouveau;

    Comme ta fonction renvoie (enfin renvoyait ) un Client (et non une référence ou un pointeur), tu as une recopie entière de nouveau. Du coup, ton pointeur *m_adress de nouveau et le pointeur *m_adress de cette copie pointaient sur la même adresse mémoire. C'est à ce moment là que ça se complique, car tu as une copie et donc l'objet "nouveau" est détruit......... le destructeur est donc appelé et le contenu de *m_adress est donc détruit aussi... Ton *m_adress de la copie ne pointe donc sur plus rien du tout, et l'utilisation de ce *m_adress fait exploser le programme !

    J'espère que j'ai été clair, car avec toutes ces adresses, on s'y perd

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Très clair, on ne saurait te remercier assez pour ton aide et la clarté de tes explications!!
    A bientot peut-être et sincèrement merci!

Discussions similaires

  1. problème avec l'apostrophe dans une requête
    Par mika0102 dans le forum VBA Access
    Réponses: 7
    Dernier message: 09/03/2019, 16h51
  2. problèmes avec "include file" pour une page asp
    Par chipsense dans le forum ASP
    Réponses: 1
    Dernier message: 02/09/2005, 15h22
  3. [Débutant] Problème avec les paramètres d'une proc stockée
    Par babulior dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 28/06/2005, 15h38
  4. Problèmes avec un TWebBrowser dans une DLL
    Par bellamyjc dans le forum Composants VCL
    Réponses: 2
    Dernier message: 12/01/2005, 22h35
  5. Problème avec un LIKE dans une procédure stockée
    Par Oluha dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 22/12/2004, 14h38

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