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 :

Constructeur par défaut ?


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut Constructeur par défaut ?
    Bonjour !
    J'ai un problème que mes connaissances en C++ n'expliquent pas :
    J'ai la classe suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class FluidParticles : public std::vector<FluidParticle> {
     
    public :
        FluidParticles(int nParticles, int X1, int X2, int Y1, int Y2);
     
     
    };
    Ainsi que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class ParticleSystem
       {
     
       private :
           bool m_wasMaxReached;
     
       public :
           FluidParticles Particles;
    [.....]
    Bref mon "ParticleSystem" contient un objet de classe "FluidParticles"

    Mon constructeur de ParticleSystem est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ParticleSystem::ParticleSystem(void)
    {        
            Particles       = FluidParticles(0,0,0,0,0);
        ...
    }
    Cependant j'ai comme erreur sous visual que la classe "FluidParticles" ne possède pas de constructeur par défaut...

    Donc je comprend pas trop ce que se passe. J'ai l'impression de comprendre qu'en fait je dois instancier mon champ "Particles" dès la déclaration dans le .hpp, mais à ce moment là comment faire? Vu qu'avant la construction les paramètres ne sont pas connus? (ils sont passés au constructeur)

    Bref je pige pas où est l'erreur ... en java ça marche !

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Moi je dirai que la classe std::vector possède un constructeur par défaut virtuel, donc le compilateur attend un constructeur par défaut pour la classe qui en hérite, même s'il n'est jamais appelé.

  3. #3
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par lezebulon
    j'ai comme erreur sous visual que la classe "FluidParticles" ne possède pas de constructeur par défaut
    L'as-tu défini ? (le constructeur par défaut)

  4. #4
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    L'as-tu défini ? (le constructeur par défaut)
    Non, mais ça veut donc dire que je suis forcé de "construire" mon objet FluidParticles Particles avant l'appel du constructeur de ParticleSystem ?

    Un constructeur par défaut, ce serait un truc qui initialiserait mes valeurs à 0 et ne prendrait pas de paramètres?

  5. #5
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @Pierre Dolez: Un constructeur ne doit pas être virtuel, donc non.

    @OP: On n'hérite pas publiquement de std::vector<>, pas de destructeur virtuel. Et ca ne marche pas car tu définis un constructeur qui prend des arguments (sans valeurs par défaut), donc le constructeur trivial n'est pas généré, donc tu n'as pas de constructeur par défaut.

  6. #6
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    @OP: On n'hérite pas publiquement de std::vector<>, pas de destructeur virtuel. Et ca ne marche pas car tu définis un constructeur qui prend des arguments (sans valeurs par défaut), donc le constructeur trivial n'est pas généré, donc tu n'as pas de constructeur par défaut.
    Donc comment je peux faire pour hériter de std::vector<> ? Je dois faire autrement?

  7. #7
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Tu ne le fais pas. Tu mets un attributs de type std::vector<> en privé. (l'héritage privé peut aussi être une solution)

  8. #8
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut
    Ok je vais faire ça alors,
    c'est juste que ça me paraissait plus élégant de faire ça que d'avoir une classe container contenant 1 attribut

  9. #9
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    C'est l'inverse (sauf cas spécifique, cf empty class). Il faut toujours préférer la relation la plus faible entre deux classes : l'héritage publique représente un IS-A, l'héritage privé un HAS-A.

    Et "avoir un" est une ralation plus faible que "être un" : la seul entité au courant de cette relation et pouvant l'utilisé est la classe qui contient, alors qu'un IS-A est visible de tous.

    La relation d'héritage (publique) ouvre la porte à de possibles mauvaises utilisation de ta classe (la considérer comme du type mère là où ca ne devrait pas par exemple), alors que l'aggrégation ne permet pas de nouveau biais, tu ne peus faire de ta classe que ce que tu as définie.

    Herb Sutter à écrit un article qui est sur GotW à propos de l'héritaga (Uses and Abuses of Inheritance). Lis le quand tu as le temps, il est très bien (il présente aussi des cas d'utilisation de l'héritage privé, protégé et multiple).

  10. #10
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut
    Bon je viens de transformer ma classe en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class FluidParticles {
     
    public :
     
        std::vector<FluidParticle> list;
     
        FluidParticles(int nParticles, int X1, int X2, int Y1, int Y2);
     
     
    };
    Mais j'ai toujours le même problème d'absence de constructeur par défaut... pourquoi ?

    edit : en transformant ma classe en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class FluidParticles {
     
    public :
     
        std::vector<FluidParticle> list;
     
        FluidParticles(int nParticles, int X1, int X2, int Y1, int Y2);
     
        FluidParticles(void);
     
    };
    ça marche, mais à ce moment-là est-ce que je suis obligé de définir le constructeur par défaut? et est-ce que je peux "ré-instancier" cet objet à la construction de l'objet qui le contient?

  11. #11
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Déjà répondu :

    Citation Envoyé par Flob90 Voir le message
    Et ca ne marche pas car tu définis un constructeur qui prend des arguments (sans valeurs par défaut), donc le constructeur trivial n'est pas généré, donc tu n'as pas de constructeur par défaut.
    En privé le vecteur (cf encapsulation).

    Qu'entends tu par ré-instancier ?

    Si tu ne veus pas avoir à réécrire le constructeur, tu peus utilisé default (si ton compilo le supporte) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FluidParticles() =default;
    Sinon il te suffit de mettre un coprs vide, ton vecteur sera initialisé correctement (il sera vide par contre).

    Les deux codes reviennent, un peu prés, au même.

  12. #12
    Membre à l'essai
    Inscrit en
    Décembre 2009
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 33
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Qu'entends tu par ré-instancier ?
    En fait je comprend pas quand est instancié mon objet de classe FluidParticles, dans la classe ParticleSystem.

    Pour moi, il est instancié uniquement quand je l'instancie explicitement dans le constructeur de ParticleSystem. C'est pour ça que je vois pas trop pourquoi j'aurai besoin de constructeur par défaut, vu que je veux jamais instancier cet objet "par défaut"

    Du coup, est-ce que dans mon programme, l'objet FluidParticles est instancié "2 fois" ? Une fois à un moment qui m'est inconnu, avec le constructeur par défaut, et ensuite est "écrasé" par l'objet que je construit pendant la construction de ParticleSystem?

  13. #13
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Quand tu rentres dans le coprs du constructeur tes attributs sont tous initialisés (sauf cas de no-initialization), ceci est fait dans la liste d'intialisation, si tu ne la mets pas explicitement elle utilise les contructeurs par défaut pour tout tes membres (et tes classes de base). Il faut donc que tu lui précises comment initialisé FluidParticles dans cette liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ParticleSystem::ParticleSystem(void) : Particles(0,0,0,0,0)
    {}
    Je te laisse voir la FaQ pour les détails sur la syntaxe (c'est en gros là même que pour les classes de base à part que tu utilises le nom de l'attribut).

  14. #14
    Invité
    Invité(e)
    Par défaut
    Du coup, est-ce que dans mon programme, l'objet FluidParticles est instancié "2 fois" ? Une fois à un moment qui m'est inconnu, avec le constructeur par défaut, et ensuite est "écrasé" par l'objet que je construit pendant la construction de ParticleSystem?
    Moi, à votre place, je ferais un petit test. Dans chacun des constructeurs ( le vrai et le vide) je mettrais une impression, type "Initialisation par le vrai constructeur" et "Appel du constructeur vide". Eventuellement la même chose avec le destructeur.

  15. #15
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonsoir,

    je pense que ton problème vient du fait que tu appelles le constructeur par défaut sans t'en rendre compte à un moment donné dans ton code.
    C'est pour cela que le compilateur te demande de le définir.

    N'aurais-tu pas une ligne de ce genre qui traîne quelque part?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ParticleSystem system; // appel au constructeur par défaut

  16. #16
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Oui il est appelé explicitement dans la liste d'intitialisation (de son autre classe).

  17. #17
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Oui il est appelé explicitement dans la liste d'intitialisation (de son autre classe).
    Ah oui!

  18. #18
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 624
    Points : 30 649
    Points
    30 649
    Par défaut
    Salut,
    Citation Envoyé par Flob90 Voir le message
    C'est l'inverse (sauf cas spécifique, cf empty class). Il faut toujours préférer la relation la plus forte entre deux classes : l'héritage publique représente un IS-A, l'héritage privé un HAS-A.

    Et "avoir un" est une ralation plus forte que "être un" : la seul entité au courant de cette relation et pouvant l'utilisé est la classe qui contient, alors qu'un IS-A est visible de tous.
    C'est justement l'inverse: l'héritage est une relation beaucoup plus forte qu'une relation de composition / d'agrégation ou qu'un héritage privé.

    Et il faut... préférer la relation la plus faible


    L'héritage (public) permet en effet de faire passer une instance de la classe dérivée pour un instance de la classe de base. On peut difficilement faire plus fort comme relation, non

    Mais, effectivement, il ne faut envisager l'héritage que lorsque l'on a de bonnes raisons (entre autre lorsque cela a réellement du sens de le faire) de le faire et sous réserve que certaines conditions soient remplies
    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

  19. #19
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Oula oui j'ai inverser faible et fort (ca m'apprendra à me relire ) (je vais éditer). Donc c'est le même message avec fort à la place de faible et vise versa xD

    J'ai bien voulu dire que la composition était à préférer, je sais pas pouquoi j'ai inversé sur le coup.

  20. #20
    Membre habitué Avatar de nowahn
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 84
    Points : 150
    Points
    150
    Par défaut
    Bonjour,

    Citation Envoyé par lezebulon
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ParticleSystem::ParticleSystem(void)
    {        
            Particles       = FluidParticles(0,0,0,0,0);
            ...
    }
    Je suppose que Particles est un membre de ParticleSystem.
    Avec ton code (initialisation dans le corps du constructeur), Particles est d’abord initialisé par défaut, puis affecté avec un nouveau FluidParticles.
    Il te faut écrire ceci :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ParticleSystem::ParticleSystem()
    : Particles(0,0,0,0,0) // initialise directement le membre avec le contructeur désiré
    {
            ...
    }

    Le code que tu as écrit est équivalent à ceci :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ParticleSystem::ParticleSystem()
    : Particles() // initialise le membre avec le contructeur par défaut
    {
            Particles       = FluidParticles(0,0,0,0,0);
            ...
    }

    Si tu ne connais pas la technique du « : », ça s’appele une « liste d’initialisation », ça permet d’initialiser directement les membres avec le bon constructeur, et évite ainsi une initialisation par défaut suivie d’une affectation.

Discussions similaires

  1. comment modifier le constructeur par défaut
    Par une_tite_question dans le forum NetBeans
    Réponses: 6
    Dernier message: 18/06/2008, 21h24
  2. notion de constructeur par défaut
    Par new_wave dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 09/05/2008, 19h33
  3. Réponses: 8
    Dernier message: 27/10/2006, 14h36
  4. Réponses: 11
    Dernier message: 25/08/2006, 16h00
  5. Constructeur par défaut en cas de surcharge
    Par gigi_m dans le forum MFC
    Réponses: 4
    Dernier message: 08/06/2005, 09h58

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