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 :

constructeurs multiples - héritage


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2006
    Messages : 19
    Par défaut constructeurs multiples - héritage
    Bonjour,

    Voilà mon contexte :

    Une classe A ayant pour constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A::A(int a) { this->a = a }
    Une classe B héritant de A ayant deux constructeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B::B() { B(0) } // appel du constructeur avec un paramètre entier
    B::B(int a) : A(a) { } // appel au constructeur de la classe parent
    Comme vous avez pu le constater ce que j'aimerais c'est que si j'instancie mon objet B sans paramètre, celui-ci appel le constructeur avec un paramètre (0 en l'occurance).
    Donc ça ça joue bien, pas de problèmes, mais j'aimerais évidemment que ma classe B appel le constructeur A lors de l'instanciation.

    Et de la manière dans laquelle je l'ai présenté ci-dessus ça ne marche pas. Compilation + Linking ok, mais erreur de segmentation lors de l'exécution.

    Mon main ressemble donc à celà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int main(void) {
    A* objet = new B();
    }
    Merci d'avance de votre aide future.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Par défaut
    Le plus simple est de déclaré un constructeur dans B avec paramètre optionnel :

  3. #3
    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 AF_2.8 Voir le message
    Le plus simple est de déclaré un constructeur dans B avec paramètre optionnel :
    Je n'ai jamais beaucoup aimé des paramètres optionnels mais c'est probablement une question de goût.
    Bref, tout ceci pour dire qu'en lisant cette réponse cela m'a fait penser que si ton constructeur n'a qu'un seul paramètre (optionnel ou pas) pense à le déclarer explicit pour éviter des comportements inattendus :
    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
    struct A
    {
        protected:
       A(int a_):a(a_){}
       ~A(){}
     
    private:
       int a;
    };
     
    struct B : public A
    {
       B(int a_=0):A(a_){}
    };
     
    struct C : public A
    {
       explicit C(int a_=0):A(a_){}
    };
     
     
    void fonction1(B){}
    void fonction2(C){}
    int main()
    {
        fonction1(1);  // convertit 1 en B(1). Est-ce vraiment voulu ???
        fonction2(1); // erreur
        fonction2(static_cast<C>(1));
        return 1;
    }

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2006
    Messages : 19
    Par défaut
    Ce que je n'ai pas précisé, c'est que dans mon constructeur "principal" je fais beaucoup d'autres opérations.

    En faisant
    Cela me permettait de placer toutes mes instructions uniquement dans le constructeur avec paramètre B::B(int a).

    Sinon oui effectivement, l'allocation dynamique est un réflexe Java... La manière présenté ci-dessus y est d'ailleurs assez courante en Java.

    EDIT: pour le constructeur explicite, c'est justement l'implémentation du polymorphisme qui m'intéresse ici, mais merci de l'info

  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
    Citation Envoyé par Rocknacro Voir le message
    Ce que je n'ai pas précisé, c'est que dans mon constructeur "principal" je fais beaucoup d'autres opérations.

    En faisant
    Cela me permettait de placer toutes mes instructions uniquement dans le constructeur avec paramètre B::B(int a).

    Sinon oui effectivement, l'allocation dynamique est un réflexe Java... La manière présenté ci-dessus y est d'ailleurs assez courante en Java.
    Dans ce cas, tu factorise ton code dans une fonction qui va faire les autres opérations, et tu invoque cette fonction dans ton constructeur:

    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
    class B : public A
    {
         public:
             B():A(0)
             {
                 doManyOtherThinks();
             }
             B(int i):A(i)
             {
                 doManyOtherThinks();
             }
        private:
            void doManyOtherThinks()
            {
                // what you want
            }
    };
    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 averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2006
    Messages : 19
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Dans ce cas, tu factorise ton code dans une fonction qui va faire les autres opérations, et tu invoque cette fonction dans ton constructeur:
    Ok c'est fait, ça me plaît pas trop j'aurais préféré tout faire dans un seul constructeur (refactoring ou pas) mais ça marche comme ça.

    Merci à tous pour vos remarques intéressantes.

  7. #7
    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 Rocknacro Voir le message
    EDIT: pour le constructeur explicite, c'est justement l'implémentation du polymorphisme qui m'intéresse ici, mais merci de l'info
    explicit c'est par rapport au polymorphisme de coercition qui peut avoir sur int pas par rapport au polymorphisme d'inclusion lié à l'héritage.

  8. #8
    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 Rocknacro Voir le message
    Bonjour,

    Voilà mon contexte :

    Une classe A ayant pour constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A::A(int a) { this->a = a }
    Très mauvaise idée...

    Il vaut toujours mieux utiliser les listes d'initialisation

    Une classe B héritant de A ayant deux constructeurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B::B() { B(0) } // appel du constructeur avec un paramètre entier
    B::B(int a) : A(a) { } // appel au constructeur de la classe parent
    On n'appelle JAMAIS le constructeur d'une classe dans un autre constructeur de la même classe !!!!

    Par contre, comme c'est le constructeur de A qui t'intéresse, tu peux invoquer explicitement celui-ci dans la liste d'initialisation, en lui passant les valeurs ad-hoc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //pour le constructeur par défaut de B
    B::B():A(0){}
    // pour le constructeur de B prenant un int
    B::B(int i) : A(i){}
    Donc ça ça joue bien, pas de problèmes, mais j'aimerais évidemment que ma classe B appel le constructeur A lors de l'instanciation.
    Tu ne peux pas l'éviter, vu que B hérite de A et donc que B EST UN A...

    Comme la base de B est A, il faut absolument s'asusrer que la partie de B qui vient de A soit correctement initialisée, sinon, tu va avoir des problèmes
    Et de la manière dans laquelle je l'ai présenté ci-dessus ça ne marche pas. Compilation + Linking ok, mais erreur de segmentation lors de l'exécution.
    Et pour cause...
    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

  9. #9
    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,
    En C++0x, tu peux enchaîner les constructeurs comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct A
    {
       A(int a_):a(a_){}
    private:
       int a;
    };
    struct B : public A
    {
       B():B(0){}
       B(int a):A(a){}
    };
    Mais mieux, en C++0x tu peux aussi hériter des constructeurs des classes de bases :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    struct A
    {
       A(int a_):a(a_){}
    private:
       int a;
    };
    struct B : public A
    {
       using A::A; // et hop, tu as naturellement un constructeur B(int) qui appelle directement A(int) !!!
    };
    LE hic ? C'est qu'aujourd'hui la délégation et l'héritage de constructeur ne sont pas encore disponibles sur les compilateurs Visual ou GCC

    Et en C++98, ce n'est pas possible d'enchaîner les constructeurs ou d'en hériter. Il te faut donc soit passer par une fonction d'initialisation dédiée si le nombre de paramètres et le contenu des constructeurs étaient complexe, soit simplement écrire à la main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B::B():A(0) { } // appel du constructeur avec un paramètre entier
    B::B(int a) : A(a) { }
    P.S. : Pourquoi une allocation dynamique ? Réflexe Java/C# ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(void)
    {
       B b;
       A& objet = b;
     
     
       return 0;
    }

  10. #10
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    LE hic ? C'est qu'aujourd'hui la délégation et l'héritage de constructeur ne sont pas encore disponibles sur les compilateurs Visual ou GCC
    Pour info, la délégation de constructeur est présent sous clang depuis quelques jours.

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

Discussions similaires

  1. Syntaxe : constructeur multiple
    Par Teo dans le forum Langage
    Réponses: 6
    Dernier message: 28/05/2008, 04h55
  2. Bonnes pratiques des constructeurs multiples
    Par TheDrev dans le forum C++
    Réponses: 6
    Dernier message: 05/05/2008, 19h06
  3. interet des constructeurs multiples
    Par pseudobidon57 dans le forum Langage
    Réponses: 2
    Dernier message: 13/06/2007, 12h33
  4. Constructeur et héritage.
    Par Pragmateek dans le forum C++
    Réponses: 3
    Dernier message: 15/08/2006, 21h01
  5. [POO] Constructeur et héritage
    Par LDDL dans le forum Langage
    Réponses: 3
    Dernier message: 23/05/2006, 21h44

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