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 :

héritage de construction


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut héritage de construction
    Bonjour,

    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) {} 
    void test();
    };
    struct B : public A {};
     
    void test() {
        A a(3);
        B b(3); // error no matching constructor for B(int)
        B b();
        b.test(); // Ok  --> jalousie : pourquoi A::test est-il accessible et pas A::A()?
    }
    Quelqu'un pourrait-il m'expliquer pourquoi il est obligatoire de déclarer un constructeur B(int) (la question du gros flemmard) ?
    En effet la sémantique de l'héritage est "est un" et donc, pour un héritage public, je m'attends à ce que TOUS les membres public et protected soient accessibles directement dans ma classe fille (selon leur classe d'accès bien sur), d'où ma question : Pourquoi tant de haine?
    Ca a une importance pour moi par rapport aux template, dans la mesure où on ne peut pas spécialiser explicitement les using :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename t> using B = UneDefinition<t>
    template <> using B<test> = A<test,autres paramètres>; // Erreur spécialisation explicite d'un 'using' interdite
    // interdit, c'est pourtant ce dont j'aurais besoin
    Je me suis dit que je pourrais remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <> struct B<test> : public A<test, autres paramètres> {};
    Mais ça m'impose de redéclarer tous les constructeurs et ça me dérange (lourdeur, maintenance), d'où ma question.

    Merci par avance pour vos réponses.

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 770
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 770
    Par défaut
    inheriting constructors (<- lien stackoverflow en anglais)


    En gros, les constructeurs ne sont pas hérités en C++03 : c'est un mix entre
    • Comme il faut initialiser les nouveaux membres, le C++ oblige de [re]définir un constructeur
    • Le compilateur n'est pas sensé savoir que le constructeur B veut appeler le constructeur A (pour ton exemple)


    En C++11 on peut utiliser using

  3. #3
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par Teaniel Voir le message
    la sémantique de l'héritage est "est un"
    C'est bien plus subtil. Les propriétés de l'héritage public font qu'il autorise une substituabilité syntaxique. Et si elle n'est pas plus riche que ça (LSP), c'est casse gueule. Très casse gueule.
    EST-UN est un faux ami. EST-SUBTITUABLE-A est bien plus exact et à préféré quand on réfléchit.

    Quant à la substituabilité du polymorphisme d'inclusion (l'héritage public), elle concerne les objets qui existent déjà. Avant la construction, un objet n'existe pas. (En plus avec les template, on change de paradigme et là... en C++ c'est ... pas le chaos... mais bon.)

    L'héritage des constructeurs est un sucre syntaxique récent (cf message de mon VDD), mais c'est juste là pour aider. Et il faut que cela soit explicite.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Bonjour,

    Merci à tous les deux pour vos réponses.
    Pour "m'aider" j'utilise toujours une image : dans la nature, les oiseaux volent. Donc un pigeon vole. Ok. Un pigeon est un oiseau. Personne ne dira le contraire.
    Pour créer un arbre, on plante (ou sème) une graine. On sait donc que la construction d'un chêne se fera ainsi. C'est comme cela que je sens l'héritage.

    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
    template <typename _T> struct A {
    A() {}
    A(int) : ... {...}
    // N autres constructeurs
    f() {}
    };
     
    template<> struct A<un_type> {
    A(float) : ... { ... }
    // P autres constructeurs
    f() {}
    };
     
    template <typename _T> struct B : public A<_T>{};
     
    void f() {
        A<un_type> a(3.5); // Ok
        B<un_type> b(3.5); // impossible
     
    }
    Dans ce cas, je suis donc obligé de reproduire les N lignes du constructeur de A dans B, puis d'ajouter une spécialisation à B pour reproduire les P constructeurs de A<un_type>, N + P constructeurs qui ne feront RIEN hormis d'appeler celui du parent... Je trouve que ça fait potentiellement beaucoup de travail pour ce RIEN...
    Je croyais que C++ était un langage concis???
    Pour moi, B<_T> est un A<_T> y compris dans sa manière d'être créé. C'est d'ailleurs si vrai que c'est bien la fonction f de A qui sera appelée si on écrit b.f();, et pas une reproduction. Pourquoi ne pourrait-on pas appeler le constructeur correspondant du parent s'il n'est pas trouvé dans l'enfant ? Ca retirerait N+P lignes de mo code, aidant ainsi à le rendre clair et compréhensible.

    C'est pourquoi vos réponses ne me satisfont pas... Désolé.

    Merci encore pour vos éclairages
    @++

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Le C++ est tout sauf un langage concis.

    Quid si on change l'invariant du fils et qu'il ne faut surtout pas laisser les constructeurs parents?
    Ce nouvel invariant peut être la conséquence d'un nouveau membre ou d'un sous ensemble de valeurs acceptables pour la spécialisation où on veut impérativement forcer une valeur sur la constructeur parent.

    Hériter les constructeurs par défaut, n'est pas forcément le bon choix.

    Bref, qu'est-ce qui ne te convient pas dans l'héritage de constructeurs du C++11 que mon VDD a évoqué?

    PS: la nature se modélise très mal en OO rien que les manchots font que c'est une véritable galère. Cherche "Principe de Substitution de Liskov", on a eu des fils très riches sur le sujet il y a des années. Lis les bien.
    On ne peut pas raisonner en termes de EST-UN. Seul EST-SUBSTITUABLE-A marche en toutes circonstances, et cela s'applique aux objets, pas aux types, sauf éventuellement dans un monde template moyennant un peu de meta-prog éventuellement
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Bonjour,

    Merci pour tes informations.
    J'ai (re à ma grande honte) lu des billets sur Liskov. Et donc ok, je me suis mal exprimé sur le 'Est un'. Merci aux anglais, qui utilisent l'expression 'Is a'...

    @foetus Désolé la dernière ligne de ta réponse m'a échappé concernant using : dans mon cas ce n'est pas possible, car cela spécialiserait un template using (mon exemple est une simplification de mon problème réel).

    Quid si on change l'invariant du fils et qu'il ne faut surtout pas laisser les constructeurs parents?
    Je dirais : surcharge. Les constructeurs ne pouvant pas être virtuels...

    Hériter les constructeurs par défaut, n'est pas forcément le bon choix.
    Je suis d'accord, mais cela peut aussi l'être. Et je parie que ça le serait beaucoup plus souvent.

    Pardonne moi mon ignorance, mais je ne sais pas ce qu'est ton VDD. C'est sans doute évident, mais moi et l'évidence...
    @++

  7. #7
    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
    Voisin Du Dessus : celui (ou ceux) qui a (ont) répondu(s) avant.

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

Discussions similaires

  1. Problème héritage et construction de classe
    Par BadThing dans le forum Langage
    Réponses: 18
    Dernier message: 19/08/2010, 17h15
  2. [Postgresql]Héritage
    Par lheureuxaurelie dans le forum PostgreSQL
    Réponses: 13
    Dernier message: 02/10/2008, 09h18
  3. [JBuilder 7] Construction d'executable natif
    Par renaudfaucon dans le forum JBuilder
    Réponses: 3
    Dernier message: 24/11/2006, 22h28
  4. [Postgres] Héritage + Clés
    Par k-reen dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 21/05/2003, 16h37
  5. Héritage entre Forms
    Par BarBal dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 17h44

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