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

Langage C++ Discussion :

surcharge opérateur =


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Points : 36
    Points
    36
    Par défaut surcharge opérateur =
    Bonjour,

    Je suis débutant en C++ et je viens du monde C#.
    J'aurais voulut savoir s'il est possible en C++ de modifier le comportement d'une classe lorqu'on lui applique l'opérateur = .

    Pour m'expliquer :

    Imaginons que j'ai une classe A du genre :

    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
     
     
    class A
        {    
            private :
     
            int _value;
     
    	public :
     
           A()
    	    {
     
                }
         }
    Si j'utilise cette classe dans le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    A classe1;
    A classe2;
     
    A classe3 = classe2;
    J'obtiens 3 instances de ma classe de type A à trois adresses différentes.
    ce que je voudrais c'est que classe3 et classe2 pointent vers la même adresse.

    Autrement dit que l'opérateur = pour mon type A ne cré pas un nouvelle instance dans un nouvel espace mémoire.

    Est ce possible et si oui comment ?

    Merci de votre aide.

  2. #2
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    D’après ce que tu décris, ce n'est pas l’opérateur = qui intervient mais un constructeur de copie.

    Pour ce que tu souhaites faire, il faut passer par une référence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A classe2;
    A& classe3 = classe2;
    classe3 est le même objet que classe2. Nul besoins de surcharger quoi que ce soit.

  3. #3
    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
    En C# tu as deux notions, les structs, et les class. En C++, tu as deux notions assez proches, mais gérées de manières assez différentes. Ces notions de valeur ou d'entité ne font pas partie du type (et déclarer un type struct ou class est quasiment identique, seule les visibilités par défaut des membres et de l'héritage sont impactées). Elles dépendent de la manière dont on manipule une instance de ce type.

    Ici, tu manipules une instance directement, c'est comme si tu manipulais une struct en C#. Quand tu déclares ainsi 3 objets, ils ont forcément un emplacement mémoire différent.

    Si tu veux avoir un comportement plus proche de celui des classes en C#, tu vas devoir manipuler tes objets pas l'intermédiaire d'un pointeur ou d'une référence. Après, le C++ est un langage assez riche, qui offre plusieurs alternative sur la manière de gérer la durée de vie des objets manipulés par pointeurs (mais pas de garbage collector par défaut, alors que c'est le moyen principal fourni par C#). Peut être le plus simple pour commencer (et assez proche d'un garbage collector, tant qu'on n'a pas de cyles genre a possède b qui possède c qui possède a) est d'utiliser les shared_ptr.

    Ton code s'écrirait alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <memory>
     
     
    std::shared_ptr<A> classe1;
    std::shared_ptr<A> classe2;
     
    std::shared_ptr<A> classe3 = classe2;
    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.

  4. #4
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par JolyLoic Voir le message

    Ton code s'écrirait alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <memory>
     
     
    std::shared_ptr<A> classe1;
    std::shared_ptr<A> classe2;
     
    std::shared_ptr<A> classe3 = classe2;
    Déclaré ainsi, aucune instance n'est crée. Je pense que tu voulais faire ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include <memory>
     
     
    std::shared_ptr<A> classe1(new A);
    std::shared_ptr<A> classe2 = std::make_shared<A>(); // forme recommandée 
     
    std::shared_ptr<A> classe3 = classe2;

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Points : 36
    Points
    36
    Par défaut
    Très bien, je vais suivre vos conseils.

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2010
    Messages : 434
    Points : 654
    Points
    654
    Par défaut
    Oui c'est possible

    Cherche du coté des classes canoniques.
    C'est une notion que je te conseil d'apprendre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    class A
    {
        public A& operator=(A&);
    }

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Points : 36
    Points
    36
    Par défaut
    Oui !

    j'ai effectivement recherché ce que voulais dire forme canonique et je suis tombé sur la notion de classe sémantique d'identité :

    "une classe a une sémantique d'entité si toutes les instances de cette classe sont nécessairement deux à deux distinctes, même si tous les champs de ces instances sont égaux. Elle modélise un concept d'identité : chaque objet représente un individu unique."

    "une classe à sémantique d'entité :

    ne redéfinit pas les opérateurs arithmétiques (+,-,/*) ;
    n'a pas d'opérateur d'affectation (=, constructeur par copie) ;
    ne redéfinit pas les opérateurs de comparaison (==, < etc.)."

    "Si on veut créer une copie d'un objet à sémantique d'entité, on s'appuie sur une méthode Clone spécifique retournant un nouvel objet dans un état semblable. "

    Cest très proche de ce que je voudrais.

    J'ai donc testé le concept :

    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
     
     
    class Livre
    {
       private :
     
       int _identifiant;
     
       Livre(const Livre& l);
     
       Livre& operator=(const Livre& l);
     
       public :
     
       Livre()
       {
          _identifiant = -1;
       }
     
       Livre(int identifiant)
       {
         _identifiant = identifiant;
       }
     
       int GetIdentifiant()
       {
          return _identifiant;
       }
     
       ~Livre()
       {}
     
    };
     
    int main(int argc, char* argv[])
    {
    	 Livre albumToto(79); 
     
    	 //Livre bandeDessinTata = albumToto;    //Compile error
     
    	 Livre& livreCopie = albumToto; 
     
    	 printf("%d", &livreCopie);
    	 printf("\n");
    	 printf("%d", &albumToto);
    	 printf("\n");
     
    	 printf("%d", livreCopie.GetIdentifiant());   //79
    	 printf("\n");
     
    	 return 0;
    }
    Ceci correspoond à ce que je voulais il me semble : cela me permet de limiter le nombre d'instance fortement et pour moi un livre est un objet unique non recopiable.

    Une dernière question : si je n'ai plus besoin de livreCopie dois je faire une opération quelconque dans le main pour m'en débarasser (sans heurter albumToto) ?

    Le chemin s'éclaire.

    Merci

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    On ne peut pas "détruire une référence", sauf en sortant du scope où elle a été créée.
    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
    int main(int argc, char* argv[])
    {
    	Livre albumToto(79); 
     
    	//Livre bandeDessinTata = albumToto;    //Compile error
     
    	{
    		Livre& livreCopie = albumToto; 
     
    		printf("%d", &livreCopie);
    		printf("\n");
    		printf("%d", &albumToto);
    		printf("\n");
     
    		printf("%d", livreCopie.GetIdentifiant());   //79
    		printf("\n");
    	}
    	//Ici, l'identifiant livreCopie n'existe plus
    	return 0;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 66
    Points : 36
    Points
    36
    Par défaut
    Je m'en doutais un peu mais je voulais en être certain.

    Merci de votre réponse.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Portabilitée : Surcharge opérateur de comparaison
    Par Dimitri_87 dans le forum C++
    Réponses: 11
    Dernier message: 15/12/2006, 16h14
  2. Surcharge opérateur +
    Par nunurs83 dans le forum C++
    Réponses: 6
    Dernier message: 31/10/2006, 09h48
  3. [Débutant]Surcharge opérateur +
    Par Geolem dans le forum Débuter
    Réponses: 13
    Dernier message: 05/12/2005, 10h16
  4. surcharge opérateur << et >>
    Par Azharis dans le forum Débuter
    Réponses: 11
    Dernier message: 02/11/2005, 21h22
  5. Surcharge opérateurs
    Par ghostdogpr dans le forum C++
    Réponses: 5
    Dernier message: 18/03/2005, 11h51

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