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 :

Besoin d'aide pour la surcharge des opérateurs == et =


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 Besoin d'aide pour la surcharge des opérateurs == et =
    Dans un de mes cours, mon professeur nous a demandé de crée une liste de Client. Donc j'ai une class Client et Liste ( la liste est faite par moi et non par la library "liste.h" )

    Je vous montre ma class Client elle ne fait pas grande chose à part stocker des information.

    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include <iostream>
    #include <string>
    using namespace std;
     
    class Clients
    {
    	string nom_;
    	string prenom_;
    	string adresse_;
    	int idClient_;
    	unsigned int nbAchat_;
    	double totalAchat_;
     
    public:
     
    	void SetNom(string nom)
    	{ nom_ = nom; }
     
    	void SetPrenom(string prenom)
    	{ prenom_ = prenom; }
     
    	void SetAdresse(string adr)
    	{ adresse_ = adr; }
     
    	void SetId(int id)
    	{ idClient_ = id; }
     
    	void SetNbAchat(int nb)
    	{ nbAchat_ = nb; }
     
    	void SetTotal(double total)
    	{ totalAchat_ = total; }
     
    	void SetAll(string nom,string prenom,string adr,int id,int nb,double total)
    	{
    		SetNom(nom);
    		SetPrenom(prenom);
    		SetAdresse(adr);
    		SetId(id);
    		SetNbAchat(nb);
    		SetTotal(total);
    	}
     
    	string GetNom() const
    	{ return nom_; }
     
    	string GetPrenom() const
    	{ return prenom_; }
     
    	string GetAdresse() const
    	{ return adresse_; }
     
    	int GetIdClient() const
    	{ return idClient_; }
     
    	int GetNbAchat() const
    	{ return nbAchat_; }
     
    	double GetTotal() const
    	{ return totalAchat_; }
     
    	friend ostream& operator<<(ostream& os, Clients& client)
    	{
    		cout << client.GetNom() << " " << client.GetPrenom() << " " << client.GetAdresse() << " " << client.GetNbAchat() << " " << client.GetTotal() << endl;
    		return os;
    	}
    };
    Dans une des méthodes de ma class liste je dois faire une comparaison d'objet ,dout le fait que j'ai besoin de surcharger l'opérateur ==

    voici la méthode :
    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
    	void RechercherCourant(Objet objet)
    	{
    		NoeudPtr courant = _tete;
    		if (_tete)
    		{
    			do 
    			{
    				if (*courant->objetPtr == objet)
    					break;
    				courant = courant->suivant;
    				if (courant == _tete)
    					courant = null;
    			}while (courant);
    		}
    		_courant = courant;
    	}
    dans mon main j'ai la variable
    Clients client;
    Liste<Clients> ListeClient;

    EDIT : je crois que j'ai trouvé comment overload l'opérateur == pour ma class mais je ne suis pas sûr si c'est la bonne méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	friend bool operator==(Clients& client1,Clients& client2)
    	{
    		return ((client1.nom_ == client2.nom_
    			&& client1.prenom_ == client2.prenom_
    			&& client1.adresse_ == client2.adresse_
    			&& client1.idClient_ == client2.idClient_
    			&& client1.nbAchat_ == client2.nbAchat_
    			&& client1.totalAchat_ == client2.totalAchat_));
    	}

  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,

    Commençons déjà par ta classe client...
    • void SetNom(string nom)
    • void SetPrenom(string prenom)
    • void SetId(int id)
    sont autant de fonctions inutiles : une fois que tu as définis les membres nom, prénom et id, tu n'as plus à les modifier, sous peine d'avoir un autre client (on pourrait dire que ces trois information te servent d'identifiant unique non ambigu )

    En plus, il est toujours préférable de transmettre une chaine de caractères sous la forme d'une référence (constante si elle ne doit pas être modifiée) plutot que par valeur, pour éviter les copies inutiles

    void SetAll(string nom,string prenom,string adr,int id,int nb,double total) n'est pas inutile, mais ne devrait pas s'appeler setAll: ce devrait etre le constructeur de ta classe client.

    int nb et double total ne seraient d'ailleurs pas nécessaire, car, lorsque le client est créé, il n'a encore fait aucun achat (ce qui fait que nb vaut d'office 0) et n'a encore fatalement rien payé (ce qui fait que total vaut aussi 0.0)

    SetNbAchat et SetTotal devraient etre regroupée en une seule fonction qui ne prendrait pas le total "général" mais le total de l'achat que le client vient de faire, et qui ne prendrait pas le nombre d'achat.

    Avec ces deux mutateurs, tu te trouves dans l'obligation d'écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    client.SetNbAchat(client.GetNbAchat()+1);
    client.SetTotal(client.GetTotal() + totalActuel);
    alors que si tu créais à la place une fonction (mettons ajouteAuxAchat) qui serait implémentée sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ajouteAuxAchat(double totalDesAchatDuJour)
    {
        totalAchat_ += totalDesAchatDuJour;
        ++nbAchat_;
    }
    il te suffirait d'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    client.ajouteAuxAchat(totalDesAchatDuJour);
    pour faire le tout de manière automatique

    Enfin,
    • string GetNom() const
    • string GetPrenom() const
    • string GetAdresse() const
    devraient renvoyer une référence constante, de nouveau, pour éviter les copies inutiles

    De manière générale, tout ce qui n'est pas un type primitif comme char, short, int, long, long long, leur version signed et unsigned, float, double et long double) mérite amplement d'être transmis (ou renvoyé, si faire se peut) par référence (constante, s'il ne faut pas les modifier) pour éviter les copies inutiles.

    La raison est simple : la copie de type "complexes" peut demander énormément de ressources, tant en mémoire qu'en temps pour l'effectuer

    Ceci étant dit : une classe Client a, typiquement ce que l'on appelle une sémantique d'entité, c'est à dire, qu'il s'agit d'une classe pour laquelle il n'existera jamais deux instances ayant les mêmes valeurs, au moins pour certains de leurs membre (le jour où je crois un philippe dunski qui habite à la même adresse que moi, je le traite de menteur )

    Typiquement, il ne sert à rien de comparer deux instances ayant sémantique d'entité "membre à membre", car seuls ceux qui permettent d'identifier une instance de manière unique et non ambigue ont de l'importance.

    Par exemple, le membre id est un quandidat idéal : chaque client aura son propre numéro d'id qui sera "unique et non ambigu" (comprend: qui permet d'identifier un client en étant sur que l'on n'en trouvera pas un autre, meme s'il a le meme nom, le meme prénom, mais une adresse ou une date de naissance différente ) De plus, on ne comparera pas deux clients entre eux, car cela n'aurait aucun sens:

    Si tu trouve le client qui s'appelle Dupont, Jaques, qui habite au 26 rue de la poupée qui tousse à Makapet - les - bains - de - pieds, qui est venu 36 fois au magasin pour un total dee 856.89€ et (surtout) qui a l'identifiant client 726, tu es sur que c'est la personne que tu cherches...

    Sauf que...

    Sauf que pour pouvoir obtenir ces informations, il faudrait... que tu aies déjà trouvé monsieur Dupont, Jaques, ayant le numéro de client 726 dans ta liste de clients

    Mais, si monsieur Dupont, Jaques (la personne que tu as physiquement en face de toi ou au téléphone, hein ?) pourra très facilement te donner son nom, son prénom et son adresse, tu auras de la chance s'il est en mesure de te donner son numéro de client, beaucoup de chance s'il peut te dire combien de fois (précisément) il est venu chez toi pour acheter, et tu devrais te dépêcher d'aller jouer à l'euromillion s'il arrive à te donner le total de ses achats avec une précision de ne serait-ce que de 10 €

    Bref, tu l'auras compris, l'opérateur == ne sert strictement à rien pour les classes ayant sémantique d'entité, simplement parce que cela compare des données qui nécessiteraient que tu aies déjà retrouvé ton client pour arriver à faire la comparaison

    Par contre, tu peux comparer certaines informations de manière séparée : le numéro de client avec un numéro que le client t'aura donné, par exemple, ou, s'il s'avère que le client s'est trompé (ou s'il ne le connait simplement pas), un ensemble correspondant à son non, son prénom et son adresse.

    Seulement, ce n'est plus un opérateur ==.

    L'idéal, dans ce cas là, est de recourir à ce que l'on appelle un foncteur ou un prédicat

    Il s'agit d'une petite structure qui ne sera composée que d'une seule fonction (éventuellement un ou deux membres si besoin): l'opérateur () qui, dans le cas qui nous intéresse, renverra un booléen.

    Nous pourrions, ainsi, avoir un foncteur qui vérifie le numéro id du client et renvoie vrai s'il correspond à un numéro que nous fournissons, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct equalById
    {
        bool operator()(Client const & cl, int id) const
        {
            return cl.GetIdClient() == id;
        }
    };
    ou un autre qui compare le nom, le prénom et l'adresse avec des informations également fournies, sous une forme 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
    struct equalByName
    {
        equalByName(std::string const & nom, std::string const & prenom,
                    std::string adresse):nom(nom),prenom(prenom),adresse(adresse){}
        std::string nom;
        std::string prenom;
        std::string adresse;
        bool operator()(Client const & cl) const
        {
            return cl.GetNom() == nom
                && cl.GetPrenom() == prenom 
                && cl.GetAdresse() == adresse:
        }
    };
    De cette manière, tu pourrais écrire quelque chose de proche dede
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int numeroDid; /* donné par le client */
    /*pour chaque client dans la liste, */
    if (equalById()(client, numeroDid) )
    {
        // c'est celui qu'on cherche
    }
     
    else
    {
        // c'est pas celui ci
    }
    ou 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
    std::string nom; //fourni par le client
    std::string prenom; // idem
    std::string adresse; // encore idem
    equalByName test(nom, prenom, adresse);
     
    /*pour chaque client dans la liste, */
    if (test(client) )
    {
        // c'est celui qu'on cherche
    }
     
    else
    {
        // c'est pas celui ci
    }
    et là, enfin, tu aurais quelque chose d'utilisable
    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
    Merci Beaucoup pour l'explication cela m'a aidé.

    Juste préciser que les SetNom, SetPreNom ... son utilise ,car dans mon program je dois avoir la posibilité de modifier les informations des clients.

  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
    Merci Beaucoup pour l'explication cela m'a aidé.

    Juste préciser que les SetNom, SetPreNom ... son utilise ,car dans mon program je dois avoir la posibilité de modifier les informations des clients.
    Accepterais tu que l'on décide de te renommer albert ou gontrand?

    Il y a des informations que tu peux modifier (comme l'adresse), mais ni le nom ni le prénom n'a à etre modifié
    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 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
    Je comprend se que tu veux dire, mais se n'est pas moi qui est fait les consignes de cette exercice et je dois les respecter ^^

  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 lolaalol Voir le message
    Je comprend se que tu veux dire, mais se n'est pas moi qui est fait les consignes de cette exercice et je dois les respecter ^^
    ... ou mieux encore, expliquer à ton prof pourquoi tu ne les respecte pas
    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
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    quoiqu'a priori, tu sois plutôt dans la situation d'expliquer pourquoi la consigne ne s'applique pas à ces champs.

    J'imagine en effet que la consigne ressemble à "codez aussi les méthodes permettant de modifier les informations du client."
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    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 leternel Voir le message
    quoiqu'a priori, tu sois plutôt dans la situation d'expliquer pourquoi la consigne ne s'applique pas à ces champs.

    J'imagine en effet que la consigne ressemble à "codez aussi les méthodes permettant de modifier les informations du client."
    Hé bien, pour une fois, c'est toi qui explicite bien mieux que moi ce que je voulais dire
    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

  9. #9
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Le nom et prenom devraient de toutes facons etre modifiables, ne serait-ce que pour permettre la correction orthographique de ceux-ci.

  10. #10
    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 Klaim Voir le message
    Le nom et prenom devraient de toutes facons etre modifiables, ne serait-ce que pour permettre la correction orthographique de ceux-ci.
    Hé bien, non...

    S'il y a eu une faute d'orthographe dans le nom ou dans le prénom, le malheureux client se retrouvera avec cette faute d'orthographe "ad vitam".

    J'ai personnellement un nom auquel les gens font une faute d'orthographe de manière quasi systématique, et tu n'imagines pas le nombre de factures que je peux recevoir où cette faute apparait.

    Et j'ai beau écrire ou faire tout ce que je peux pour que mon nom soit corrigé, il ne l'est jamais

    Ceci dit, si vraiment la correction orthographique du nom ou du prénom s'avère nécessaire, alors, il faudra mettre en place une classe bien particulière, qui sera seule autorisée à modifier ces informations.

    A ce moment là, l'amitié entre ta classe client et cette classe particulière permettra d'éviter d'exposer une information (ou ici, un comportement) plus que nécessaire.

    En effet, si tu place un mutateur public sur le nom ou sur le prénom, cela implique que tout ce qui utilise un objet de type client pourra y accéder

    le fait de déclarer une classe amie de ta classe client lui permettra d'accéder à ses membres privés de manière beaucoup plus controlée, et tu auras donc l'assurance que, si modification du nom et du prénom il y a, ce sera dans un "environnement clairement controlé"
    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

  11. #11
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Effectivement.

Discussions similaires

  1. [MySQL] Besoin d'aide pour la création des boucle
    Par runcafre91 dans le forum PHP & Base de données
    Réponses: 15
    Dernier message: 02/03/2010, 12h33
  2. Réponses: 9
    Dernier message: 25/11/2008, 16h44
  3. [ZF 1.5] [Route] Besoin d'aide pour la configuration des mes routes => url propre
    Par Jonathan.b dans le forum Zend Framework
    Réponses: 5
    Dernier message: 29/10/2008, 14h27
  4. Réponses: 2
    Dernier message: 27/05/2008, 18h57
  5. Besoin d'aide pour un MCD des tables de la BDD
    Par nicaud dans le forum Schéma
    Réponses: 3
    Dernier message: 23/04/2006, 10h34

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