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 :

Heritage et constructeurs : les constructeurs doivent ils toujours être rédéclarés et redéfinis ?


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut Heritage et constructeurs : les constructeurs doivent ils toujours être rédéclarés et redéfinis ?
    Bonjour tout le monde,

    Je vous écris car je me retrouve confronté à un cas que je ne suis pas certain de comprendre: j'ai deux classes : une classe mère et une classe fille. Fille hérite de mère. Est ce que fille doit redécalrer et définir les constructeurs déclarés et présents dans la classe mère? Je ne le pensais pas mais le code suivant fonctionnne :

    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
     
    class mere
    {
    private:
        int member;
    public:
        mere(/* args */) =default;    
        inline explicit mere(int setupvalue) : member(setupvalue){std::cout<<"construction mere"<<std::endl;};
        virtual ~mere()= default;
        inline virtual int proceed (int a){return a;};
    };
     
    class fille : public mere
    {
    private:
        /* data */
    public:
        fille(/* args */) { std::cout << "Fille" << std::endl; };
        explicit fille(int a) :  mere(a) { std::cout << "construction fille" << std::endl; }; //fonctionne
        ~fille() override = default;
    };
    //main.cpp
    int main(int, char**){
        std::cout << "Hello, from vtableTests!\n";
        fille test(5);
        std::cout<<test.proceed(5)<<std::endl;
    }
    alors que le code suivant (le même que celui au dessus mais en supprimant le constructeur de fille ligne 19) ne fonctionne pas :


    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
     
    class mere
    {
    private:
        int member;
    public:
        mere(/* args */) =default;    
        inline explicit mere(int setupvalue) : member(setupvalue){std::cout<<"construction mere"<<std::endl;};
        virtual ~mere()= default;
        inline virtual int proceed (int a){return a;};
    };
     
    class fille : public mere
    {
    private:
        /* data */
    public:
        fille(/* args */) { std::cout << "Fille" << std::endl; };
        //explicit fille(int a) :  mere(a) { std::cout << "construction fille" << std::endl; }; //ne fonctionne pas
        ~fille() override = default;
    };
     
    //main.cpp
    int main(int, char**){
        std::cout << "Hello, from vtableTests!\n";
        fille test(5);
        std::cout<<test.proceed(5)<<std::endl;
    }
    Je pensais que le constructeur de fille allait naturellement chercher celui de la mère ...

  2. #2
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut log des erreurs
    Pour info voici le log des erreurs :


    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
    35
    36
    37
     
    [main] Building folder: vtable all
    [build] Starting build
    [proc] Executing command: /usr/bin/cmake --build /home/user123/programmation/test/vtable/build --config Debug --target all -j 22 --
    [build] Scanning dependencies of target vtableTests
    [build] [ 50%] Building CXX object CMakeFiles/vtableTests.dir/main.cpp.o
    [build] [ 50%] Building CXX object CMakeFiles/vtableTests.dir/fille.cpp.o
    [build] [ 75%] Linking CXX executable vtableTests
    [build] [100%] Built target vtableTests
    [driver] Build completed: 00:00:00.595
    [build] Build finished with exit code 0
    [main] Building folder: vtable all
    [build] Starting build
    [proc] Executing command: /usr/bin/cmake --build /home/user123/programmation/test/vtable/build --config Debug --target all -j 22 --
    [build] Scanning dependencies of target vtableTests
    [build] [ 25%] Building CXX object CMakeFiles/vtableTests.dir/main.cpp.o
    [build] [ 50%] Building CXX object CMakeFiles/vtableTests.dir/fille.cpp.o
    [build] /home/user123/programmation/test/vtable/main.cpp: In function ‘int main(int, char**)’:
    [build] /home/user123/programmation/test/vtable/main.cpp:6:17: error: no matching function for call to ‘fille::fille(int)[build]     6 |     fille test(5);
    [build]       |                 ^
    [build] In file included from /home/user123/programmation/test/vtable/main.cpp:2:
    [build] /home/user123/programmation/test/vtable/fille.hpp:10:5: note: candidate: ‘fille::fille()[build]    10 |     fille(/* args */) { std::cout << "Fille" << std::endl; };
    [build]       |     ^~~~~
    [build] /home/user123/programmation/test/vtable/fille.hpp:10:5: note:   candidate expects 0 arguments, 1 provided
    [build] /home/user123/programmation/test/vtable/fille.hpp:5:7: note: candidate: ‘constexpr fille::fille(const fille&)[build]     5 | class fille : public mere
    [build]       |       ^~~~~
    [build] /home/user123/programmation/test/vtable/fille.hpp:5:7: note:   no known conversion for argument 1 from ‘int’ to ‘const fille&’
    [build] gmake[2]: *** [CMakeFiles/vtableTests.dir/build.make:82: CMakeFiles/vtableTests.dir/main.cpp.o] Error 1
    [build] gmake[2]: *** Waiting for unfinished jobs....
    [build] gmake[1]: *** [CMakeFiles/Makefile2:879: CMakeFiles/vtableTests.dir/all] Error 2
    [build] gmake: *** [Makefile:136: all] Error 2
    [proc] The command: /usr/bin/cmake --build /home/user123/programmation/test/vtable/build --config Debug --target all -j 22 -- exited with code: 2
    [driver] Build completed: 00:00:00.217
    [build] Build finished with exit code 2

  3. #3
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Je pensais que le constructeur de fille allait naturellement chercher celui de la mère ...
    Sauf que vous n'avez aucun constructeur de la classe fille qui prend un "int" en entré.

    (En plus, si la classe mère a plusieurs constructeurs, lequel appeler ?)

    Et remarque à 2 balles, c'est les constructeurs des classe de bases qui est appelé avant le constructeur de la classe dérivée, donc, faut pas trop simplifier le travail du compilateur.

    => Soyez explicite, le compilateur, il aime pas deviner.

  4. #4
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut
    Merci pour la réponse,

    Mais je ne saisis pas pourquoi :
    • avec le constructeur fille(int) le compilateur ne va pas chercher mere(int)
    • avec la fonction proceed si je tape fille.proceed(int) le compilateur va bien trouver la fonction mere.proceed(int) déclarée et définie dans la classe mère


    Est ce que ça vient du fait que l'objet n'est pas encore construit ?

  5. #5
    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
    En fait, c'est parce que le constructeur n'est pas une fonction normale. C'est une notation pour une opération spéciale.

    Le constructeur de fille n'a pas le même role que le constructeur de mere.

    proceed fait partie des membres de mere, elle fait donc partie des membres de fille.
    le constructeur ne fait pas partie de la classe, il n'est pas appelable.

    On ne peut pas écrire fille f; f.fille(1);.

    Techniquement, le code complet d'un constructeur, c'est l'initialisation de chaque membre de l'objet, dans leur ordre de déclaration, en commençant par ses classes de bases, récursivement, puis le corps du constructeur.
    Ici, c'est donc la mère mère::mère(int)(qui va récursivement construire mère::member) puis les membres de fille.
    Si rien n'est précisé, l'initialisation d'un membre ou d'une classe de base passe par son constructeur par défaut, s'il est disponible (sinon, la compilation échoue)

  6. #6
    Membre confirmé
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Par défaut
    merci @ternel et merci @bacelar

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 150
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par awawawa Voir le message
    avec le constructeur fille(int) le compilateur ne va pas chercher mere(int)
    Parce qu'un constructeur c'est pas un appel de méthode simple, et le compilateur ne vas pas lire ton esprit pour deviner quel constructeur tu veux appeler.
    Il va pas non plus s'amuser à décider qu'un constructeur avec des paramètres similaires ou identiques existent donc on va l'utiliser.
    Si tu ne veux pas de constructeur fille qui fasse quelque chose de spécifique et juste réutiliser celui de mere : using mere::mere; mais ça bouge tous les constructeurs de mere dans fille...
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 03/04/2015, 16h25
  2. [OL-2010] Les "Callback" fonctionnent-ils toujours sous 2010 ?
    Par RobKris63 dans le forum VBA Outlook
    Réponses: 0
    Dernier message: 05/05/2014, 16h57
  3. Les annuaires sont-ils toujours utiles ?
    Par rodolphebrd dans le forum Référencement
    Réponses: 1
    Dernier message: 07/01/2014, 11h44
  4. Les éditeurs doivent-ils écouter leurs clients ?
    Par Hinault Romaric dans le forum Actualités
    Réponses: 20
    Dernier message: 08/08/2013, 09h48

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