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 :

Composition, références/pointeurs et posession


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut Composition, références/pointeurs et posession
    Salut à toutes et à tous !

    Je reviens vous embêter un chouïa...

    Quand j'ai commencé le C++ (il y a ... houla, au moins 4 mois ) j'ai suffisamment lu des phrases du style "utiliser les références partout où vous devez, et les pointeurs quand vous pouvez pas faire autrement" pour tenter d'appliquer ce principe à la lettre. Donc j'ai mis des références partout où j'avais besoin de polymorphisme : dans les constructeurs, dans les données membres... Je partais du seul principe que pour peu que l'instance existe déjà, je peux utiliser une référence sur son type ancêtre pour activer le polymorphisme, et basta.
    Et ça a marché un temps.
    J'avais bien fait un ou deux new à un moment, mais comme je ne savais pas exactement comment gérer la mémoire, que je préfère ne pas faire les choses plutôt que de les faire salement, j'ai choisi de mettre aucun delete, en attendant que ça me retombe sur la tronche pour m'en occuper sagement/proprement. ça n'a pas tardé, on est en plein dedans.

    Donc là j'ai commencé à arpenter pas mal de sites sur les références, les pointeurs, les pointeurs intelligents etc. J'ai commencé à voir que mon principe d'utilisation (objet déjà instancié + polymorphisme requis = reference) était pas si bon que ça, qu'il y avait aussi un truc appelé "ownership", qu'on finit bien par avoir besoin de créer un objet dynamiquement, et qu'il faut bien le détruire à un moment où à un autre et que la destruction est un grand pouvoir impliquant de graaandes responsabilités.

    J'ai aussi lu que si une fonction utilisait une référence sur un objet, elle "renonçait" à sa propriété. C'est le point qui précisément m'inquiète. Parce que j'ai fait de la composition en folie, en utilisant des références sur les composantes. Je me rend bien compte que par le jeu des références il est bien maladroit de détruire les membres-composantes via le destructeur de l'objet-composite.

    Typiquement, dans le code suivant, les membres/composants peuvent être de plusieurs types, donc j'avais besoin de polymorphisme. D'un autre côté, au moment de construire un objet A, je savais exactement de quelle classe héritant de J j'avais besoin. Donc j'ai codé ça avec des références sur J, en laissant à un builder le soin de construire dynamiquement les composantes c1 et c2 selon les options que je lui donne, puis de les filer au constructeur de A.

    Seul souci : qui détruit ces objets c1 et c2 au final ? Je pense que c'est à A de les détruire, parce que sortis de A, c1 et c2 n'ont aucun sens. Mais si c'est le cas, va falloir que je modifie toutes mes interfaces/tests/implémentations ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    class A :{
        public:
            A(J & c1, J & c2);
            virtual ~A();
     
        protected:
        private:
            J& m_c1;
            J& m_c2;
     
    };
    Donc est-ce que je remplace toutes les références sur les composantes par des pointeurs ?
    Merci d'avance de votre réponse,
    Bien cordialement,

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    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 397
    Par défaut
    Si c'est à A de les détruire, alors tu vas devoir remplacer tes références par des pointeurs intelligents (notamment std::unique_ptr<>).
    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.

  3. #3
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Hello,

    Citation Envoyé par Seabirds Voir le message
    Seul souci : qui détruit ces objets c1 et c2 au final ? Je pense que c'est à A de les détruire, parce que sortis de A, c1 et c2 n'ont aucun sens. Mais si c'est le cas, va falloir que je modifie toutes mes interfaces/tests/implémentations ? ,
    Vu ton code, non, A utilise c1 et c2 sans se soucier de leur durée de vie. Celui que crée un A (et qui passe des refs c1 / c2) devra gérer la destruction de c1 / c2 (et s'assurer qu'ils vivent assez longtemps.

    Si A possède c1 / c2, ton code devrait plutôt ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct A {
       A(std::unique_ptr<J>&& c1, std::unique_ptr<J>&& c2):
          m_c1(std::move(c1)),
          m_c2(std::move(c2))
       { }
     
       std::unique_ptr<J> m_c1;
       std::unique_ptr<J> m_c2;
    };
    Ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct J {
       J(int i, float f) { /*...*/ }
    };
     
    struct A {
       A(int i1, float f1, int i2, float f2):
          m_c1(std::make_unique<J>(i1, f1)),
          m_c2(std::make_unique<J>(i2, f2))
       { }
     
       std::unique_ptr<J> m_c1;
       std::unique_ptr<J> m_c2;
    };

  4. #4
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Il n'y a pas de smiley "dévotion absolue"...

    Mille merci pour vos réponses, c'est exactement ce que je cherchais.
    Bon, en route pour les modifications

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    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 397
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Si A possède c1 / c2, ton code devrait plutôt ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct A {
       A(std::unique_ptr<J>&& c1, std::unique_ptr<J>&& c2):
          m_c1(std::move(c1)),
          m_c2(std::move(c2))
       { }
     
       std::unique_ptr<J> m_c1;
       std::unique_ptr<J> m_c2;
    };
    C'est un peu redondant là non? Si c1 et c2 sont déjà en déclarés en &&, on ne devrait pas avoir besoin du std::move(), si?
    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.

  6. #6
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    @Médinoc, aucune idée, je met les deux parce que je sais que ça marche comme ça. Mais oui, ça marche peut être sans le std::move.

  7. #7
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    @Médinoc, aucune idée, je met les deux parce que je sais que ça marche comme ça. Mais oui, ça marche peut être sans le std::move.
    Ça ne fonctionne pas sans, c1 et c2 sont vues comme des références, non comme une rvalue.
    Pour généraliser, toute variable est une référence, std::move est donc obligatoire.

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    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 397
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Ça ne fonctionne pas sans, c1 et c2 sont vues comme des références, non comme une rvalue.
    Pour généraliser, toute variable est une référence, std::move est donc obligatoire.
    Je croyais que std::move() faisait juste un cast de T& en T&&?
    Et c1 et c2 sont déjà des std::unique_ptr<J>&&...
    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.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 21/12/2014, 20h03
  2. Passage par référence/pointeur
    Par NiamorH dans le forum C++
    Réponses: 5
    Dernier message: 15/07/2008, 10h05
  3. [pointeurs/référence]
    Par poukill dans le forum C++
    Réponses: 18
    Dernier message: 10/05/2006, 11h49
  4. Références et pointeurs sur un tableau
    Par smag dans le forum C++
    Réponses: 2
    Dernier message: 01/03/2005, 20h29
  5. Réponses: 8
    Dernier message: 26/08/2004, 18h59

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