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 multiple en C++ : pourquoi l'héritage d'interfaces est insuffisant [Tutoriel]


Sujet :

C++

  1. #1
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut Héritage multiple en C++ : pourquoi l'héritage d'interfaces est insuffisant
    Bonjour à tous !

    Je viens de mettre en ligne un article, intitulé : Héritage multiple en C++ : Pourquoi l'héritage d'interfaces est insuffisant

    N'hésitez pas à faire donner votre avis, faire des remarques. L'article compare aussi des fonctionnalités de différents langages orientés objet, principalement C++, C# et Java. En tant que tel, j'espère qu'il pourra susciter des discussions intéressantes, sans sombrer dans le troll inter-langages.

    Bonne lecture !
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  2. #2
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Super plaidoyer pour l'héritage multiple

    Enfin quelqu'un qui défend cette notion qu'il est "politiquement correct" de décrier.

    Merci

    juste 2 remarques :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    assert(montant > solde());
    J'espère que tu ne développe pas pour une banque !

    Et au chapitre 3-B, je me demande si le 1er diagramme de classe est correct (classe A définie 2 fois), et s'il l'est, il me semble identique au 2eme (même si on comprend bien grace à ces 2 diagrammes ce que tu veux montrer).

    Du bon boulot en tous cas.

    jmv

  3. #3
    screetch
    Invité(e)
    Par défaut
    Salut,
    c'est un très bon papier


    mais pour la partie 2B, je ne suis pas sur que l'héritage (multiple ou pas) soit la bonne solution, on dirait plutôt que quelqu'un a abusé de l'héritage. Dans ce cas, il faudrait plutot faire de la composition que de l'héritage (c'est un problème que je retrouve dans toutes les bibliothèques IHM que je connais; faire un widget c'est environ 8 niveaux d'héritage)

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par jmv Voir le message
    juste 2 remarques :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    assert(montant > solde());
    J'espère que tu ne développe pas pour une banque !
    Rassure toi, tu peux dormir sur tes deux oreilles
    Citation Envoyé par jmv Voir le message
    Et au chapitre 3-B, je me demande si le 1er diagramme de classe est correct (classe A définie 2 fois), et s'il l'est, il me semble identique au 2eme (même si on comprend bien grace à ces 2 diagrammes ce que tu veux montrer).
    En effet, je ne pense pas qu'UML permette d'exprimer cette notion, et mes diagrammes ne sont donc probablement pas des diagrammes UML standards. Encore un exemple qui démontre que malgré ses désirs d'universalité, UML a été pensé avec certains types de langages en tête, et ne permet pas vraiment de représenter toutes les notions de tous les langages.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par screetch Voir le message
    mais pour la partie 2B, je ne suis pas sur que l'héritage (multiple ou pas) soit la bonne solution, on dirait plutôt que quelqu'un a abusé de l'héritage. Dans ce cas, il faudrait plutot faire de la composition que de l'héritage (c'est un problème que je retrouve dans toutes les bibliothèques IHM que je connais; faire un widget c'est environ 8 niveaux d'héritage)
    Je suis assez d'accord avec toi, le domaine de l'IHM abuse généralement des hiérarchies d'héritage profondes, et obligent souvent à dériver des classes fournies par la bibliothèque pour personnaliser le comportement (même si je trouve que la situation s'améliore, par exemple, en WPF, on peut faire moult personnalisations sans aucune dérivation, avec entre autre la notion de templates d'affichage qui permet d'indiquer comment un composant graphique logique va créer ses composants graphiques visuels).

    Le fait est qu'il faut tout de même faire avec. Et si le cas des IHM est emblématique des cas où l'on doit dériver de classes d'une hiérarchie existante et non modifiable, il n'est pas le seul.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Article super intéressant , à faire lire à tous les javateux et autres csharpeux qui ne comprennent pas pourquoi on se sent frustré quand on code dans leur langage chéri.

    Seule petite remarque, je trouve dommage de présenter le NVI pour vérifier les contrats comme un avantage à l’héritage multiple de code. C’est plus un palliatif moins mauvais que ce qu’on a dans les autres langages. Théoriquement, les contrats font partie de l’interface de la fonction, pas de son code. Je ne l’aurais en tout cas pas mis en premier, je trouve les deux autres exemples beaucoup plus convaincants .

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 36
    Points : 85
    Points
    85
    Par défaut
    Très intéressant bravo !
    Surtout que je me suis dev C# et qu'en se moment je me met au c++, ça tombe à pic .

    J'ai survolé pour l'instant, mais je peut dire que sans héritage multiple, on peut aussi ne pas dupliquer de code, en général grâce à la composition.
    ça évite aussi d'avoir des classes "qui font tout", 1ère chose à laquelle je pense quand je vois écrit héritage multiple.

    En tout cas merci, j'ai hâte de m'y plonger ce soir

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Excellent, j'ai appris beaucoup de choses
    Find me on github

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    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 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Hello.
    Super initiative. Je vais y gagner en moins de radotage grâce à toi Merci !

    Je ne suis pas super fan des exemples sur les widgets. Essentiellement parce que nous sommes dans un cas de base commune. De fait dans ces cas là j'ai un red flag qui se lève et je tends à me méfier pour utiliser le MI.
    Avec deux sources différentes, je n'ai plus aucun scrupule. Mais il est vrai que l'on rejoint là les politiques (mais sans l'aspect template)(mince j'ai oublié le nom donné aux classes à destructeur protégé non-virtuel dans le C++CS de Sutter&Alexandrescu, ce n'était pas "politique" il me semble, mais autre chose)

    En ordre d'importance, je place comme Loic le NVI parmi l'argument principal. Les politiques viennent ensuite.

    Je serai revenu sur le LSP dans la partie sur les problèmes : Pour que le MI marche, il faut a minima comprendre et respecter le LSP sur chaque axe d'héritage. Quand on commence à tout mélanger, c'est là que l'on ne s'en sort plus. Et le gros problème du MI, c'est souvent que l'héritage simple n'était pas compris. Comment étendre sereinement à plus d'une classe sous de telles conditions ?
    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...

  10. #10
    Membre confirmé

    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 104
    Points : 614
    Points
    614
    Par défaut
    Bonjour,

    C'est un article très intéressant qui réveille quelques interrogations que je me pose quant à la mise en œuvre de l'héritage multiple.

    Dans l'exemple 3-A (où il manque la déclaration d'héritage au passage), on définit que B est un A et que C est un A. Mais D qui est un B et un C n'est pas "un" A, il multiplie les qualités de A. Cela me semble contre intuitif.

    Ainsi, j'ai le sentiment que l'héritage en losange est le résultat naturellement attendu quand on hérite plusieurs fois d'une même classe. Or ce n'est pas le comportement par défaut.

    De plus, comme la qualité de l'héritage de A est définit au niveau de B et C, j'ai l'impression qu'aucun type d'héritage n'est satisfaisant. Par exemple, à supposer que j'écrive une bibliothèque où A, B et C sont définies sans héritage virtuel et qu'un utilisateur de ma bibliothèque définisse un D héritant de B et C. Il se retrouve dans l'impossibilité de choisir un héritage en losange. Du coup, lors d'un appel à une fonction de la bibliothèque prenant un A, il devra choisir s'il s'agit du A de B ou du A de C.

    Alors quel comportement adopter en pratique pour ne pas bloquer les futurs développeurs ni les évolutions du logiciel ? Faut-il tout mettre en héritage virtuel ?

  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
    @j-jorge: Si il n'y a pas d'héritage virtuel, alors en effet un D n'est pas un A (tu peux tester, une instance de D ne peux pas être donné là où un A est attendu, LSP). Pourquoi la relation "est un" serait toujours transitive ?

  12. #12
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Ainsi, j'ai le sentiment que l'héritage en losange est le résultat naturellement attendu quand on hérite plusieurs fois d'une même classe. Or ce n'est pas le comportement par défaut.
    Suivant les idiomes du C++, je ne trouve pas que ce soit un résultat naturellement attendu. Habituellement le C++ manipule tout par valeur, ce qui sous entends qu'un agregat de deux types, quels que soient leur relations, est équivalent (moyennant agencements mémoire) à deux objets de ces deux types "collés ensembles" du point de vue de la mémoire. Or ce principe ignore totalement le fait que les deux types pourraient avoir une base commune qui est donc répétée pour chaque type parcequ'ils ont chacun un état séparé.

    Du coup, la solution de l'héritage virtuel m'apparait comme une exception parceque contrairement aux idiomes habituels du C++, cette feature permet de dire explicitement au language qu'on sait qu'il y a une relation entre les types et qu'on veut que leurs états soient partagés.

    Je ne sais pas pour vous, mais il m'est arrivé rarement d'avoir recours à l'héritage virtuel, pour une hierarchie bien précise. Du coup j'ai plutot tendance à penser que c'est cela l'exception, et que l'heritage multilpe tout court est juste plus facile à penser par défaut.

    En fait, je me dit qu'il n'y a que dans des cas de hierarchies prédéfinies et fixes (c'est à dire qui n'est pas fait pour être étendu) que c'est vraiment utile. Mais j'imagine que je manque de pratique dans le sujet.

  13. #13
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Je ne sais pas pour vous, mais il m'est arrivé rarement d'avoir recours à l'héritage virtuel, pour une hierarchie bien précise. Du coup j'ai plutot tendance à penser que c'est cela l'exception, et que l'heritage multilpe tout court est juste plus facile à penser par défaut.
    En général, si tu as de l’héritage en losange, c’est parce que tu as un super objet. Comme en C++ on essaie d’éviter de recourir à des super objets, le cas est forcément peu fréquent.

  14. #14
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    En général, si tu as de l’héritage en losange, c’est parce que tu as un super objet. Comme en C++ on essaie d’éviter de recourir à des super objets, le cas est forcément peu fréquent.
    C'est pas bête. Je n'utilises que rarement les super objets...

    L'autre cas où j'ai du jongler avec l'héritage virtuel c'était pour faire une sorte de mixin sur deux axes pour définir des "interpolations"... mais c'était un peu overkill j'imagine : http://www.ogre3d.org/forums/viewtop...44879&p=308589

  15. #15
    Membre averti
    Avatar de David Fleury
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 253
    Points : 307
    Points
    307
    Par défaut
    Merci pour cet article.
    C'est très clair et enrichissant.

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 168
    Points : 140
    Points
    140
    Par défaut
    Je trouve la partie 1 & 2 bien. Par contre la 3ème partie c'est du survol et je trouve ça dommage.

    On explique pas réellement comment fonctionne l'héritage virtuel et quel est le coût de son utilisation (j'aimerais bien le savoir).

    Je trouve la partie sur le cast trop rapide. Il manque une schématisation d'une classe mono héritage versus multi héritage pour bien comprendre l'histoire de décalage du pointeur lors du cast.

    Après un rappel sur la RTTI n'aurait pas été de refus quand on en arrive au dynamic_cast.

    Il y a une erreur dans l'exemple : 3-A.

    Mais merci pour cette article.

  17. #17
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Drannor Voir le message
    Je trouve la partie sur le cast trop rapide. Il manque une schématisation d'une classe mono héritage versus multi héritage pour bien comprendre l'histoire de décalage du pointeur lors du cast.

    Après un rappel sur la RTTI n'aurait pas été de refus quand on en arrive au dynamic_cast.
    surtout que le dynamic_cast ne compile pas sur cet exemple, puisque pour utiliser le dynamic_cast il faut une table de méthode virtuelle (c'est la qu'on stocke l'info RTTI)

  18. #18
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Drannor Voir le message
    On explique pas réellement comment fonctionne l'héritage virtuel et quel est le coût de son utilisation (j'aimerais bien le savoir).
    Peut être parce que c'est un détail d'implémentation et que ça varie d'un compilateur (voire d'une version/option de compil/code particulier) à l'autre?
    En général, entre un héritage simple et un héritage multiple, on ne fait que cumuler les vtable, et, en bonus, en cas d'héritage virtuel, on rajoute un offset (soit dans la vtable avec gcc, soit à part dans VC si ma mémoire est bonne). Dynamiquement, le cross cast peut aussi être impacté (toujours avec de l'héritage virtuel). Mais, voilà. A quoi cela peut servir d'avoir ce coût ?

  19. #19
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 168
    Points : 140
    Points
    140
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    A quoi cela peut servir d'avoir ce coût ?
    Connaître comment une fonctionnalité est implémentée permet de comprendre l'impact sur les performances (exécution & mémoire) que cela peu avoir surtout quand on fait du temps réel embarqué comme c'est mon cas.

  20. #20
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Drannor Voir le message
    Connaître comment une fonctionnalité est implémentée permet de comprendre l'impact sur les performances (exécution & mémoire) que cela peu avoir surtout quand on fait du temps réel embarqué comme c'est mon cas.
    Sans contexte, connaitre l'implémentation est intéressant. Cependant, ces aspects de coûts restent pour moi un faut débat (ou une illusion) : quel est le coût amené par le langage versus quel est le coût amené par la complexité du projet et son design ? AMHA, le principal contributeur en empreinte mémoire/temps d'exécution se situe entre le clavier et la chaise, pas sur les features du langage utilisé.

Discussions similaires

  1. Réponses: 4
    Dernier message: 05/06/2008, 23h20
  2. [heritage][conception]héritage multiple en java!
    Par soulhouf dans le forum Langage
    Réponses: 9
    Dernier message: 25/08/2005, 20h03
  3. L'héritage multiple est-il possible en Delphi ?
    Par SchpatziBreizh dans le forum Langage
    Réponses: 8
    Dernier message: 30/06/2005, 11h30
  4. utilisez vous l'héritage multiple ?
    Par vodosiossbaas dans le forum C++
    Réponses: 8
    Dernier message: 13/06/2005, 20h25
  5. [XML Schemas]héritage multiple
    Par nicolas_jf dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 10/06/2003, 12h55

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