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 :

construction automatique de membres


Sujet :

C++

  1. #1
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut construction automatique de membres
    Salut à tous,

    Est il possible de demander au constructeur de ne pas construire [tout de suite] des membres au moment de l'appel du constructeur d'une classe?

    Parce que imaginons:

    class A{
    B b;
    }
    S'il n'y a pas de constructeur par défaut de B, je suis obligé de le passer à la liste d'initialisation. Le problème c'est que j'ai besoin de faire quelques opérations avant de pouvoir construire le membre b.

    Comment faire ?

  2. #2
    screetch
    Invité(e)
    Par défaut
    si tu dois faire ca il y a sans doute moyen de couper ta classe en deux. L'autre possibilité est d'avoir un B* au lieu d'un B.

  3. #3
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    en fait j'avais pensé aux pointeurs, mais ca m'avait pas l'air assez c++
    ca peut pas se faire avec des références ?

    pour le découpage de classe, j'essaye de regarder mais j'ai l'impression que ca fait que reporter le problème à une autre classe.

    et sinon, comment tu fais pour répondre aussi vite aux messages ?

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 321
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 321
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mamelouk Voir le message
    en fait j'avais pensé aux pointeurs, mais ca m'avait pas l'air assez c++
    Parfois on est contraint d'utiliser des pointeurs en C++. Ce n'est pas interdit. D'ailleurs, tu es typiquement dans une situation où tu n'as pas le choix

    Citation Envoyé par mamelouk Voir le message
    ca peut pas se faire avec des références ?
    Ca dépend ce que tu veux faire exactement, mais à priori je dirais non car tu ne peux pas déclarer une référence dans l'instancier.

    et sinon, comment tu fais pour répondre aussi vite aux messages ?
    Et aussi bien?

  5. #5
    screetch
    Invité(e)
    Par défaut
    Pour le "aussi vite", c'est que des fois les gens tombent dans le "batch de reponse", je rafraichis le navigateur toute les heures et si tu as poste il y a une minute tu es dans le meme batch que celui qui a poste il y a une heure!!

    Pour le aussi bien, c'est que j'ouvre ma gueule seulement sur les sujets ou j'ai pieds, je vais pas aller causer sur le sujet des VARIANTS en COM car la j'ai peur du ridicule ^^"

    si tu veux faire un truc bien C++ utilise std::auto_ptr.
    Cela signifie que c'est un membre sous forme de pointeur (ce qu'on veut, pour pouvoir faire une initialisation plus tard) et dont on est l'unique proprietaire, c'est a dire pas de refcounting ou toute ces betises. C'est donc aussi contraignant que si tu avais b en membre, mais ca reste un pointeur. Et tu n'auras pas besoin de desallouer l'objet, l'auto_ptr s'en chargeant tout seul. Lorsque je passe des membres qui etaient "inline" dans la classe en pointeur, je passe toujours par la.

  6. #6
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    ouaw c'est magique. je connaissais pas ce auto_ptr, je vais voir ca

  7. #7
    screetch
    Invité(e)
    Par défaut
    pour etre precis c'est auto_ptr<T>, c'est un template. D'un coup ca devient moins magique et plus filppant ^^

    Pour faire court,

    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
     
    class A
    {
      // B b; disparait
      std::auto_ptr<B> b;
      A();
    }
     
    A::A() :
      b(0) // pas encore preeet!
    {
      // calcule, calcule
      b.reset(new B(trucs compliques)); // reinitialise le pointeur avec la nouvelle valeur, 
       //libere l'ancienne au cas ou mais y'en avait pas
    }
     
    A::~A()
    {
      // je ne me soucie pas de la liberation de b, l'auto_ptr sait se detruire tout seul
    }

  8. #8
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Je ne sais pas si ça s'applique dans ton cas mais quelque chose que je fais très souvent c'est grosso modo :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    namespace
    {
      B CreateB( stream& s )
      {
        int x;
        s >> x;
        return B( x );
      }
    }
    A::A( stream& s )
      : b( CreateB( s ) )
    {}
    (on peut aussi varier avec des pointeurs, des std::auto_ptr, etc..)
    En fait j'en abuse un peu même, mais j'y peux rien j'aime pas avoir du code dans le corps des constructeurs

    MAT.

  9. #9
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    en effet c'est une solution dans ce style que je cherchais au début.

    mais je vais regarder du coté des auto_ptr plutot

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    La solution à base de pointeurs qui t'a été proposée est très mauvaise:
    - ton objet ne fait plus partie de ton objet, mais est simplement référencé par ton objet. Pour y accéder, tu dois faire de nombreux référencements etc.
    - tu fais de l'allocation et de la libération de mémoire dynamique, ce qui a un certain coût et nécessite de porter attention à la propriété de la donnée. Par exemple il est particulièrement dangereux d'utiliser auto_ptr de cette façon, car si tu copies ton objet alors l'ancienne copie ne réferencera plus rien.

    La solution, tout simplement, c'est d'avoir comme membre un type POD de la même taille et du même alignement que B, de le reinterpret_caster pour appeler explictement ses constructeurs, constructeurs par copie, opérateur d'affectation, destructeurs, etc. quand tu le souhaites. Bref c'est quand même relativement lourd à trimballer.
    De plus, il faut faire assez attention aux exceptions dans le constructeur.
    boost.optional fait plus ou moins tout ça automatiquement sauf que cela a un coût : il a en plus un booléen indiquant si l'objet est initialisé ou non.

    De toutes manières, il n'y a normalement aucune raison qui justifie de ne pas pouvoir initialiser correctement ta variable dès la liste d'initialisation.

  11. #11
    screetch
    Invité(e)
    Par défaut
    je reconnais que ma solution a des desavantages mais la tienne m'a fait sursauter.

  12. #12
    screetch
    Invité(e)
    Par défaut
    j'avais oublie que auto_ptr avait une copie possible, my bad, j'utilise perso un scoped_ptr (fait rapidos maison) qui ne sait pas se copier, ce qui interdit la copie de celui qui le possede. Cela reste suffisant dans 99% des cas.

  13. #13
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 321
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 321
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par loufoque Voir le message
    - ton objet ne fait plus partie de ton objet, mais est simplement référencé par ton objet. Pour y accéder, tu dois faire de nombreux référencements etc.
    Je ne suis pas persuadé que de gagner 2 cycles soit si important que cela.
    Citation Envoyé par loufoque Voir le message
    - tu fais de l'allocation et de la libération de mémoire dynamique, ce qui a un certain coût et nécessite de porter attention à la propriété de la donnée. Par exemple il est particulièrement dangereux d'utiliser auto_ptr de cette façon, car si tu copies ton objet alors l'ancienne copie ne réferencera plus rien.
    C'est évident que l'utilisation de pointeur nécessite quelques précautions, mais bon, est-ce vraiment la peine de sortir l'artillerie lourde pour si peu?

    Les cas où les contraintes sur les performances nécessitent les amélioration que tu propose sont extrêmement rares, tout de même.

  14. #14
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par screetch Voir le message
    j'avais oublie que auto_ptr avait une copie possible, my bad, j'utilise perso un scoped_ptr (fait rapidos maison) qui ne sait pas se copier, ce qui interdit la copie de celui qui le possede.
    Si tu mets un const std::auto_ptr pour stocker les membres ça fait exactement ça...

    MAT.

  15. #15
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    ou sinon:
    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
     
    class B
    {
    int m_i;
     
    public:
     
    B(int i):m_i(0)
    {
     
    }
    void Create(int i=0)  //les même argument que les constructeur.
    {
      mi=i;
    }
     
    };
    class A
    {
    int m_x,m_y;
    B b;
     
    public:
     
    A(int x,int y):b(0),m_x(x),m_y(y)
    {
     
      m_x=m_x*m_x;
      m_y=m_y*m_y;
     
      b.Create(m_x+m_y);
    }
     
    };
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  16. #16
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Si tu mets un const std::auto_ptr pour stocker les membres ça fait exactement ça...
    auto_ptr transfère les données lors d'une copie.
    C'est un comportement assez gênant, et d'ailleurs c'est pour cela qu'il sera déprécié dans le prochain standard.

  17. #17
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par loufoque Voir le message
    auto_ptr transfère les données lors d'une copie.
    Oui mais pas un const auto_ptr...
    Par exemple dans le code suivant :
    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
    namespace
    {
        class A
        {
        };
        class B
        {
        public:
            B() : a_( new A ) {}
        private:
            const std::auto_ptr< A > a_;
        };
    }
     
    BOOST_AUTO_TEST_CASE( const_auto_ptr_can_save_the_day )
    {
        B b1;
    //    B b2( b1 );
        B b3;
    //    b3 = b1;
    }
    Les deux lignes en commentaire ne compilent pas alors qu'elles compilent (et font n'importe quoi du coup) si on retire le const devant la déclaration de A::a_;

    Mais il ne faut pas avoir besoin de changer a_, c'est sûr...

    MAT.

  18. #18
    screetch
    Invité(e)
    Par défaut
    ben le but etait un peu de faire _a.reset() quand ca arrangeait ^^

Discussions similaires

  1. Réponses: 10
    Dernier message: 12/02/2013, 16h49
  2. créer automatiquement des membres dans une classe
    Par katebe dans le forum Windows Forms
    Réponses: 15
    Dernier message: 08/01/2008, 12h21

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