Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème: Constructeur de copie et opérateur =

Petit conflit entre les deux

Sujet résolu
    29 juin 2007 à 1:39:24

    Bonsoir/jour
    J'ai suivi et fini les tutoriaux. J'ai essayé de me coder une classe Fichier afin de manipuler facilement des fichiers (comme string avec les chaînes quoi). Ainsi, j'ai d'abord un constructeur de copie comme suit:
    Fichier::Fichier(const Fichier &original)
    {
            erreur("Interdit d'initialiser un fichier avec un autre!");
    }

    -> C'est tout bête, je veux juste ne pas autoriser de faire par exemple "Fichier monfichier = autrefichier;"

    D'un autre côté, j'ai surchargé l'opérateur = comme suit:
    Fichier Fichier::operator=(Fichier &original)
    {
            string contenu = original.contenu();
            this->setContenu(contenu);
            return *this;
    }

    -> Je choppe le contenu du fichier après le =, et je le colle dans le fichier avant le =.

    Résultat: Le contenu est bien copié, mais j'ai quand même le message d'erreur ! C'est-à-dire que à la fois la méthode operateur= et le constructeur de copie sont appelés. En réalité, le constructeur de copie est appelé au moment précis du "return *this;". Mais si je l'enlève ça marche plus vraiment (logique). Savez-vous d'où peut venir l'erreur ? Je sais que vous manquez d'information mais j'ai écris l'essentiel.

    Si vous avez besoin d'infos précises hésitez pas à me demander, et si vous préférez chercher dans le code, vous pouvez récupérer les fichiers à cette adresse: spotzup.free.fr/sdz.

    Ps: J'ai passé l'aprem à écrire cette classe, pitié !
    • Partager sur Facebook
    • Partager sur Twitter
      29 juin 2007 à 1:57:09

      Pour interdire la construction par copie, il suffit de déclarer en privé le constructeur par copie.

      Sinon, tu as le droit de ne pas mettre de valeur de retour pour l'opérateur que tu définis toi-même, mais ce ne serait pas idiomatique comme méthode.

      Par contre, pourquoi interdire la construction par copie et autoriser l'affectation ? C'est pas cohérent comme manière de faire.
      Normalement, si on interdit le premier, on interdit aussi le second.
      • Partager sur Facebook
      • Partager sur Twitter
        29 juin 2007 à 2:26:35

        En mettant le constructeur de copie en private ça ne change rien, j'ai toujours ce message.
        Si j'enlève le return, au lieu du message d'erreur j'ai une liste de chemin et de caractères bizarres, en tout cas ça ne va as non plus.
        Quand a mon envie d'autoriser seulement l'affectation, c'est parce que lorsqu'on créé un objet de type Fichier, on doit obligatoirement lui donner un chemin d'emplacement. Une fois créé, on peut facilement lui donner le même contenu qu'un autre fichier, mais il doit avoir son emplacement propre.

        Edit: Je viens de remarquer un autre problème, c'est que je ne peux aps faire d'affectations multiples. Si j'écris "fichier1 = fichier2 = fichier3;" après les avoir déclarés, j'obtiens le message d'erreur suivant :
        erreur: no match for "operator=" in "fichier2 = Fichier::operator=(Fichier&)(((Fichier&)(& fichier3)))"
        Comme si mon opérateur = ne renvoyait pas un objet de type Fichier. Je pense que tous mes problèmes sont liés, mais si personne ne voit d'ou ça vient j'abandonnerai tout.
        • Partager sur Facebook
        • Partager sur Twitter
          29 juin 2007 à 4:12:29

          Ah oui, c'est normal que ton appel au constructeur par copie a quand même marché, vu qu'il est appelé depuis une fonction membre.

          Et sinon, j'ai dit une bêtise, la forme canonique de l'opérateur= c'est de renvoyer une référence non constante vers l'objet !

          Ecris : Fichier& Fichier::operator=(Fichier const&);
          Et non pas Fichier Fichier::operator=(Fichier const&);

          Oui, l'argument devrait être une référence constante.

          Là il te sera possible de chaîner les affectations.
          • Partager sur Facebook
          • Partager sur Twitter
            29 juin 2007 à 8:47:53

            Tu renvois une copie => le constructeur de copie est appellé.
            • Partager sur Facebook
            • Partager sur Twitter
            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
              29 juin 2007 à 13:52:53

              En effet c'était le problème, merci de vos réponses.

              Je n'ai plus de soucis avec ça mais il se trouve que (fichier2 = fichier1) est bien un objet de type Fichier mais toujours vide, alors que c'est sensé renvoyer fichier2 il me semblait (avec le "return *this"). Pourtant fichier2 a vraiment pris la valeur de fichier1 lorsqu'on les ouvre classiquement. Bref ces erreurs viennent sûrement du fait que je commence, j'ai du mal penser ma classe et tout, je laisse là ce projet j'essaierai autre chose. Je met donc ça résolu à contrecœur ^^
              • Partager sur Facebook
              • Partager sur Twitter
                29 juin 2007 à 21:00:37

                Ben, si tu renvoies une référence, vers *this, le constructeur par copie ne sera pas appelé. T'as essayé ?
                • Partager sur Facebook
                • Partager sur Twitter
                  29 juin 2007 à 22:32:37

                  Oui c'est bon j'ai précisé que ce que vous m'aviez dit marchait, en effet si je me servait pas de référence il est logique que c'était une copie qui était créée (c'est même appris dans le cours, c'est l'une des trois façon d'appeler le constructeur de copie). Mais après ça j'ai eu un autre problème qui me semble plus spécifique mais à force de m'entraîner le truc viendra ^^
                  • Partager sur Facebook
                  • Partager sur Twitter
                    29 juin 2007 à 23:04:59

                    Attention au fait que copier des handlers de fichiers ne sera pas simple à ton niveau. Les flux du C++ ne sont pas copiables, et ce n'est pas innocent.

                    Relis le tuto de matthéo qui explique comment écrire un constructeur de copie et dis-toi bien que :
                    1- on a exactement les mêmes problématiques avec les opérateurs d'affectation
                    2- la mémoire n'est qu'un cas particulier de ressource. Les fichiers en sont un autre, de même que les sockets, les pots de peinture, ...
                    • Partager sur Facebook
                    • Partager sur Twitter
                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.

                    Problème: Constructeur de copie et opérateur =

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown