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 :

Constructeur de copie


Sujet :

Langage C++

  1. #1
    Membre confirmé Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Par défaut Constructeur de copie
    Bonjour,

    Je doit créer deux classe chacune composé de l'autre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class A
    {
        private:
            B* _b;
        public:
            A(const A &a);
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class B
    {
        private:
            A* _a;
        public:
            B(const B &b);
    };
    Le problème c'est que A(const A &a); appelle B(const B &b); et B(const B &b); appelle A(const A &a);.
    J'ai donc une boucle infinie dans mon code.

    Cordialement,
    Robinson des bois

  2. #2
    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
    Par défaut
    Oui, mais seulement si tu as besoin de copiler l'objet pointe. Si tu ne fais que copier le pointeur ca ira. Par contre ca posera un probleme parceque tu ne saurais pas quel objet dois liberer le pointeur membre.

    Est-ce que c'est A qui dois faire un delete sur sont membre ou est-ce qu'il ne fais que reference un objet qui est detenu par un autre systeme?

    Si A dois faire le delete, je pense que le plus simple c'est d'utiliser shared_ptr (C++11 ou boost), de maniere a ce que lors de la copie tu ne copies que le pointeur, et le delete se fera quand aucun objet n'auras un shared_ptr sur ton membre.

    Enfin, si tu as reellement besoin de cloner ton membre dans les deux types, alors tu as effectivement un probleme de cycle, et dans ce cas c'est pas naturel, donc tu dois avoir un probleme de design de ton systeme. Dans ce cas la il faudrait nous en dire plus sur ce que tu essaies de mettre en place comme systeme.

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Bonjour,
    Les deux sont composées d'un pointeur sur l'autre, donc il n'y a pas d'appel obligatoire.

    Il doit bien y avoir un null quelque part.

    Si le problème est juste d'écrire l'en-tête, commence par une "forward declaration" de B, qui déclare la classe sans la définir.
    B sera un type incomplet, uniquement utilisable comme pointeur ou référence (B* ou B&), jusqu'à que le code rencontre sa définition explicite.

    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
    #ifndef TWO_CLASSES_H
    #define TWO_CLASSES_H
    class B;
    class A {
        private:
            B* _a;
        public:
            A(const A &b);
    };
    class B {
        private:
            A* _a;
        public:
            B(const B &b);
    };
    #endif
    Si le problème n'est pas là, montre nous plus de contexte/code.

  4. #4
    Membre confirmé Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Par défaut
    @Klaim : J'utilise mes deux pointeurs. Mais j'ai effectivement besoin que du pointeur pas de l'objet.

    @leternel : non mon problème ne viens pas de là : class B;
    Mon code compile mais il y à une boucle infinie.


    Je ne vous est pas mis toutes les variables membres.
    La boucle ce déclenche avec cette ligne de code :
    for (int i=0; i < _nbSecteurs; i++)
    _listeSecteur[i] = new secteur(*listeSecteur[i]);

    //----------Secteur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class secteur
    {
        private:
            site *s;
        public:
            secteur();
            secteur(const secteur &sec);
            ~secteur();
            secteur(site *s);
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    secteur::secteur(const secteur& sec) 
    {
        s = new site(*sec.get_site());
    }

    //----------Site
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class site
    {
        private:
            vector <secteur*> sect;
     
        public:
            site();
            ~site();
            site(const site &s);
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    site::site(const site &s)
    {
        for (int i=0; i<nb_secteur; i++)
            sect.push_back(new secteur(*s.get_secteur(i)));
    }

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    dis mois un peu:

    Chaque site peut avoir plusieurs secteurs, mais un secteur donné n'est jamais rattaché qu'à un seul site particulier, nous sommes bien d'accord

    De plus, lorsque tu vas vouloir accéder à un secteur donné d'un site particulier (car on pourrait parfaitement envisager qu'il y ait plusieurs sites distincts ), tu voudras être sur que tout ce que tu fais sur le secteur en question soit bel et bien appliqué à ce secteur là, et pas à un autre, nous sommes toujours d'accord

    Dés lors, te semble-t-il ne serait-ce que à moitié cohérent que d'accepter de créer une copie de ton site ou de ton secteur, sachant que si tu acceptes de créer cette copie, ce que tu feras à la copie ne sera pas "répercuté" vers l'original

    De mon avis personnel, (mais je me doute que tu seras encore d'accord avec moi ) il serait totalement incohérent de permettre que cela arrive, non

    La raison est bien simple: tes classes secteur et site ont sémantique d'entité parce que chaque secteur et chaque site doit, à un instant T, ne pouvoir exister qu'une et une seule fois en mémoire (autrement, tu n'aurais sans doute pas pris la peine de créer un table de... pointeur sur secteur )

    Il ne faut donc pas essayer de créer un constructeur par copie, mais plutôt envisager d'interdire, purement et simplement, la copie (et il faut d'ailleurs aussi envisager d'interdire purement et simplement l'affectation )

    Si tu as la chance de pouvoir travailler avec C++11, le plus facile est de déclarer le constructeur par copie et l'opérateur d'affectation comme "delete", 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
    15
    16
    17
    18
    19
    20
    21
    22
    class secteur
    {
        private:
            site *s;
        public:
            secteur();
            secteur(const secteur &sec) = delete;
            secteur & operator= (const secteur &) = delete;
            ~secteur();
            secteur(site *s);
    };
    class site
    {
        private:
            vector <secteur*> sect;
     
        public:
            site();
            ~site();
            site(const site &) = delete;
            site & operator=(const site & ) = delete;
    };
    Si tu ne peux pas utiliser C++11, la solution pour arriver à un résultat similaire est de déclarer SANS LES DEFINIR le constructeur par copie et l'opérateur d'affectation dans l'accessibilité privée, 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class secteur
    {
        private:
            site *s;
            /* !!!! NE PAS FOURNIR D'IMPLEMENTATION DANS LE CPP */
            secteur(const secteur &sec);
            secteur & operator= (const secteur &);
        public:
            secteur();
            ~secteur();
            secteur(site *s);
    };
    class site
    {
        private:
            vector <secteur*> sect;
            /* !!!! NE PAS FOURNIR D'IMPLEMENTATION DANS LE CPP */
            site(const site &);
            site & operator=(const site & );
     
        public:
            site();
            ~site();
    };
    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

  6. #6
    Membre confirmé Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Par défaut
    Chaque site peut avoir plusieurs secteurs, mais un secteur donné n'est jamais rattaché qu'à un seul site particulier, nous sommes bien d'accord
    Oui c'est cela. Et effectivement ma cardinalité pour les sites est supérieur à 1.

    tes classes secteur et site ont sémantique d'entité
    Je ne connaissais pas ce concept. Je vais implémenter une fonction clone() pour voir.


    PS: Je travaille effectivement avec C++11.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par robinsondesbois Voir le message
    Je ne connaissais pas ce concept. Je vais implémenter une fonction clone() pour voir.
    Grand bien te fasse, mais... En as tu réellement besoin

    Je pose sincèrement la question parce que le fait de pouvoir cloner un objet n'est pas forcément une obligation.

    Si cela peut être très intéressant / utile / nécessaire (biffer les mentions inutiles ) dans certaines circonstances, pour certains projets, ce n'est pas forcément le cas de manière systématique

    Seul le cadre de ton projet peux te permettre de répondre à cette question, dont, essentiellement, le fait que ta classe secteur peut intervenir (ou non) dans une hiérarchie de classe, par exemple
    PS: Je travaille effectivement avec C++11.
    Alors, il faut avouer que l'option de marquer les constructeur par copie et opérateur d'affectation comme delete est clairement la meilleure.

    Sois toutefois attentif au fait que, malheureusement, même VS2012 ne propose pas encore cette fonctionnalité (enfin, il ne le faisait pas la dernière fois que j'ai vérifié... peut etre une mise à jour récente l'a-t-elle apportée )
    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

  8. #8
    Membre confirmé Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Par défaut
    Ce n'était pas moi qui est créé le projet, je ne peut donc pas toucher à tous le code et à la conception. Je suis donc obligé de passer par des fonction clone.

    En tous cas merci à tous pour vos réponses prompts et utile

    Robinson des bois

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par robinsondesbois Voir le message
    Ce n'était pas moi qui est créé le projet, je ne peut donc pas toucher à tous le code et à la conception. Je suis donc obligé de passer par des fonction clone.
    Même pas forcément, à partir du moment où ton code peut faire appel au constructeur "normal".

    Le cas dans lequel tu aurais éventuellement besoin d'une fonction clone serait celui d'une fabrique manipulant une collection de différentes sortes de secteurs, voire de différentes sortes de sites, et utilisant un algorithme quelconque pour sélectionner la sorte de secteur / site qu'elle va créer.

    Essayes de faire sans, vois si cela pose problème, et, si tu as effectivement un problème quelque part, à ce moment là, tu peux envisager la fonction clone.

    Mais tu ne dois pas envisager la fonction clone comme une alternative à la copie: tu dois, surtout, essayer de faire en sorte de corriger tous les endroits où une copie est effectuée de manière indue (en gros, chaque fois qu'une copie est effectuée alors que tu voulais continuer à travailler sur le meme secteur / site )
    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

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

Discussions similaires

  1. [résolu]les constructeurs de copie
    Par pouss dans le forum Langage
    Réponses: 9
    Dernier message: 28/06/2005, 10h57
  2. Réponses: 3
    Dernier message: 24/04/2005, 14h19
  3. [C++]Heritage et constructeur de copie
    Par matazz dans le forum C++
    Réponses: 2
    Dernier message: 25/03/2005, 12h31
  4. Constructeur de copie modifiant le paramètre ?
    Par Nicodemus dans le forum C++
    Réponses: 4
    Dernier message: 12/01/2005, 21h25
  5. Constructeur de copie et Template: Transtypage
    Par ikkyu_os dans le forum Langage
    Réponses: 9
    Dernier message: 26/12/2004, 22h29

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