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 :

[POO] surcharger = pour qu'il fasse appel au constructeur de copie


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Software engineer
    Inscrit en
    Août 2008
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Software engineer

    Informations forums :
    Inscription : Août 2008
    Messages : 139
    Par défaut [POO] surcharger = pour qu'il fasse appel au constructeur de copie
    salut
    j'ai ecrit un constructeur de copie et je veux que l'operateur = lui fait appel
    je crois que : "par defaut l'operateur = fait une simple copie des attributs" . puisque ma classe contient des pointeurs , les affectations provoquent des violation memoire !
    je pense que : "si l'opérateur = fait appel a mon constructeur de copie je peux eviter ces erreurs.
    est ce que c'est faisable ce je suis entrain de raconter ? si oui comment ?
    merci d'avance

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Un petit peu de recherche t'aurais fait découvrir cette merveilleuse discussion de la semaine dernière et qui doit répondre à ton problème.

  3. #3
    Membre confirmé
    Homme Profil pro
    Software engineer
    Inscrit en
    Août 2008
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Software engineer

    Informations forums :
    Inscription : Août 2008
    Messages : 139
    Par défaut
    je crois aussi que si je surcharge le = pour qu'il fait appel au constructeur de copie ,il doit au debut faire appel au destructeur pour libérer l'espace memoire allouer par l'objet a affecté(a gauche de =) puis je fait appel au constructeur de copie .
    c'est realisable ou je dit du n'importe quoi ?

    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
     
    /***********main.cpp*************/
    int main(){
    /***********************1. Saisir deux expressions**************************/
    Expression expr1;
    Expression expr2;
        cout << "donner la premiere expression : " ;
        cin >> expr1;
        cout << "donner la deuxieme expression : " ;
        cin.sync();  //vider le flux entrant
        cin >> expr2;
     
    /**********************2. Afficher les deux expressions.************************/
        cout << "la premiere expression : " << expr1 << endl;
        cout << "la deuxieme expression : " << expr2 << endl;
     
    /******3. Trier les fractions des deux expressions selon l'un des modes de son choix (croissant ou décroissant):****/
    Expression expr3;
    char ch=0;
    encore: cout << "Appuier sur \'c\' pour trier l'expression dans l'ordre croissant" << endl;
            cout << "Appuier sur \'d\' pour trier l'expression dans l'ordre decroissant" << endl;
     
        cin >> ch;
     
        switch (ch)
        {
        case 'c' :
        case 'C' :
            cout << "l'expression triee dans l'ordre croissant est : ";
            expr3=expr1.trier1();
            cout << expr3 << endl;
            break;
        case 'd' :
        case 'D' :
            cout << "l'expression triee dans l'ordre decroissant est : ";
            expr3=expr1.trier2();
            cout << expr3 << endl;
            break;
        default :
            goto encore;
        }
     
     
    /***********************4. Evaluer la somme de la 1ère expression.**************************/
        Fraction frac_som;
        frac_som=expr1.somme();
        Expression expr_som;
        expr_som=expr_som.insert(frac_som);
        cout << "Evaluation de la 1ère expression : "<< expr_som << endl;
     
     
    /**************************5. Echanger les deux expressions******************************/
        expr3=expr1;
        expr1=expr2;
        expr2=expr3;
     
        cout << "la premiere expression : " << expr1 << endl;
        cout << "la deuxieme expression : " << expr2 << endl;
     
        return 0;
    }
    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
     
    /************Expression.h*************/
    #ifndef DEF_EXPRESSION
    #define DEF_EXPRESSION
     
    #include <iostream>
    #include "fraction.h"
    #include "ElementListe.h"
     
    using namespace std;
     
    class Expression{
        public:
        Expression();
        Expression(const Expression& e);
        Expression& insert(Fraction val);
        ElementListe *getDebut();
        int getTaille();
        void affiche();
        Fraction& somme();
        Expression& trier1();
        Expression& trier2();
        ~Expression();
     
        private:
        int taille;
        ElementListe *debut;
        ElementListe *fin;
    };
    istream& operator>>(istream& is, Expression& expr);
    ostream& operator<<(ostream& os, Expression& expr);
     
    #endif

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par oswalidos Voir le message
    je crois aussi que si je surcharge le = pour qu'il fait appel au constructeur de copie ,il doit au debut faire appel au destructeur pour libérer l'espace memoire allouer par l'objet a affecté(a gauche de =) puis je fait appel au constructeur de copie .
    c'est realisable ou je dit du n'importe quoi ?
    C'est pour ça qu'il y a utilisation d'un swap et d'une variable temporaire (le paramètre par valeur):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    MaClasse& MaClasse::operator=(MaClasse tmp) //par valeur
    {
    	Swap(tmp);
    	return *this;
    }// A la sortie tmp est détruit et les pointeurs ayant été échangés, le précédent sera détruit.
     
    void MaClasse::Swap(MaClasse &other)
    {
    	std::swap(m_pointeur, other.m_pointeur);// On échange les pointeurs
    }

  5. #5
    Membre confirmé
    Homme Profil pro
    Software engineer
    Inscrit en
    Août 2008
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Software engineer

    Informations forums :
    Inscription : Août 2008
    Messages : 139
    Par défaut
    merci
    mon cas est un peu different ,les pointeurs pointent vers des objets qui pointent vers des autres etc , une liste chainé .
    puisque j'ai pas bien saisi comment ce "swap" fonctionne, je suis encore bloqué !

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Le swap se content d'échanger une valeur par une autre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    swap(a, b):
       tmp=b
       b=a
       a=tmp
    Comme ce sont des pointeurs, tu auras juste un échange de pointeurs. Ton point critique est dans la construction par copie où il faut que toute ta chaîne de pointeur soit recopiée.
    P.S.: pourquoi utilises-tu une telle chaine plutôt que des types std: std::list par exemple?

  7. #7
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    je me permet une petite aparté pour demandé pourquoi on passe par une méthode swap qui fait appel à std::swap plutôt que de passer directement par un std::swap? Il me semble avoir toujours vu l'idiome du copy and swap avec le std::swap ? (cf la faq)

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Goten Voir le message
    je me permet une petite aparté pour demandé pourquoi on passe par une méthode swap qui fait appel à std::swap plutôt que de passer directement par un std::swap? Il me semble avoir toujours vu l'idiome du copy and swap avec le std::swap ? (cf la faq)
    std::swap fait appel à l'opérateur =. Donc si dans ta classe tu fais appel au std::swap dans la surcharge de l'opérateur =, tu auras une récursion infinie.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    MaClasse& MaClasse::operator=(MaClasse tmp) //par valeur
    {
    	std::swap(*this,tmp);// -> va appeler MaClasse::operator=, qui va appeller std::swap(MaClassse), qui va appeler MaClasse::operator=, qui va...
    	return *this;
    }

  9. #9
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    hum... alors la faq est fausse ou une subtilité m'échappe?


    http://cpp.developpez.com/faq/cpp/?p...GE_affectation

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Goten Voir le message
    hum... alors la faq est fausse ou une subtilité m'échappe?
    Je pense que tu fais référence à cette partie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    MaClasse& MaClasse::operator =(const MaClasse& Other)
    {
        // Utilisation du constructeur par copie pour copier la ressource MaClasse
        MaClasse Temp(Other);
     
        // Réaffectation : on prend les nouvelles données dans Temp, et on lui
        // donne les données à détruire en échange
        std::swap(Temp.Ressource, this->Ressource);
     
        return *this;
    }
    Ici, tu remarqueras que le swap ne se fait pas sur l'instance de MaClasse mais sur un membre 'Ressource'. Donc, il n'y a pas récursion: swap faisant appel à l'opérateur = adéquat. Si 'Ressource' est un pointeur, alors on échange les adresses. Si Ressource est une instance, alors l'opérateur '=' de ressource (s'il en a un) doit veiller à ne pas faire de swap sur lui-même.

  11. #11
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    hum en effet il échange un membre. Désolé pour la confusion

  12. #12
    Membre confirmé
    Homme Profil pro
    Software engineer
    Inscrit en
    Août 2008
    Messages
    139
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Software engineer

    Informations forums :
    Inscription : Août 2008
    Messages : 139
    Par défaut
    je n'arrive pas a comprendre pourquoi si j'ignore le destructeur , le constructeur de copie , le surcharge de = , il n'ya plus d'erreur !
    je crois que meme ça fonctionne sans probleme je doit les definir pour une meilleur gestion de memoire , n'est ce pas ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Oui, tu dois.
    Donc, pourquoi ne pas faire comme on te dit?

    PS: En théorie, pour être complètement "safe", une classe donnée ne doit pas gérer elle-même (cad, dans le corps de son constructeur et de son destructeur) plus d'une ressource. Mais là, je chipote...

    PPS: J'ai l'impression que dans ton modèle objet, tu confonds liste et chaînon...
    Tu devrais en faire deux classes différentes, c'est beaucoup plus facile à gérer.
    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.

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Reprenons dans l'ordre:
    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
    class A
    {
    public:
       A()
       :m_piMonBuffer(new int)
       {}
     
       A(const A&_ra)
       :m_piMonBuffer(new int(*_ra.m_piMonBuffer))
       {
       }
       ~A()
       {
          delete m_piMonBuffer;
       }
       A&operator=(A _ra)
       {
          Swap(_ra);
          return *this;
       }
       void Swap(A &_ra)
       {
          std::swap(m_piMonBuffer,_ra.m_piMonBuffer);
       }
     
    protected:
       int *m_piMonBuffer;
    };
     
    int main(int argc, char **argv)
    {
       {
          A a1;//1 
          A a2;// 2 
          a1 = a2;// 3
       }
       //4
     
    	return 0 ;
    }
    Etapes:
    1: appel du constructeur pour a1: allocation d'un buffer p1
    2: appel du constructeur pour a2: allocation d'un buffer p2
    3.1: appel du constructeur par copie pour une instance temporaire aT avec allocation d'un buffer pT (et avec *pT = *p2, c'est bien les valeurs qui sont recopiées et non les adresses).
    A ce moment, on a:
    -> a1 avec le buffer d'adresse p1
    -> a2 avec le buffer d'adresse p2
    -> aT avec le buffer d'adresse pT
    3.2: On entre dans l'opérateur = avec this = a1 et _ra=aT. Le buffer de this est p1 et celui de _ra et pT.
    3.3: On fait le swap. On a donc: le buffer de this/a1 est pT et le buffer de _ra/aT est p1
    3.4: On sort de l'opérateur=:
    A ce moment, on a bien:
    -> a1 avec le buffer d'adresse pT
    -> a2 avec le buffer d'adresse p2
    -> aT avec le buffer d'adresse p1
    3.5: on appel le destructeur de A pour l'instance temporaire aT: donc on libère le buffer p1.

    4: on appel le destructeur de a1 et a2: tout est OK

Discussions similaires

  1. Template - Appelé le constructeur de copy
    Par Erakis dans le forum Langage
    Réponses: 6
    Dernier message: 06/02/2008, 22h42
  2. [CSS] Etirer mon bloc pour qu'il fasse la hauteur de la page
    Par FraktaL dans le forum Mise en page CSS
    Réponses: 7
    Dernier message: 10/01/2006, 01h59
  3. [POO-Héritage] Appel du constructeur en PHP4.3.2
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2005, 15h37
  4. [POO] Surcharge d'opérateurs []
    Par Amnesiak dans le forum Langage
    Réponses: 28
    Dernier message: 11/11/2005, 12h44
  5. Aide svp pour un fontion d'appel de menu
    Par setea7 dans le forum Langage
    Réponses: 2
    Dernier message: 02/10/2005, 01h15

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