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 :

Double héritage (virtuel et non virtuel)


Sujet :

Langage C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut Double héritage (virtuel et non virtuel)
    Bonjour,

    Quel peut être l'intérêt d'une telle construction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class C : public virtual A, public B
    {
       ...
    }
    ?

    Notez qu'un seul des deux héritage est virtuel, et que A et B n'héritent de rien.

    Cela doit avoir un rapport avec la délégation à une classe soeur, mais Parashift reprend la construction en diamant pour illustrer cela.

    Ça serait d'ailleurs bien que la FAQ soit plus précise sur cette histoire d'héritage virtuel.

  2. #2
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    La FAQ est précise je trouve...
    Si D hérite de C il pourra choisir d'appeler lui-même le constructeur de A.

    (Le cas d'héritage en diamant est un cas où il est obligé de le faire)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Hors de tout contexte, cela n'a pas beaucoup d'intérêt...

    Ce qu'il faudrait voir, ce sont les relations d'héritage des classes qui dérivent de C mais on peut s'attendre, d'une manière ou d'une autre, à ce qu'elles dérivent publiquement de C et d'une autre classe (non C) dérivée de A (mais pas de B).

    Le but de l'héritage virtuel est de faire en sorte qu'il n'y ait qu'une représentation de la classe ancêtre en mémoire car, si on s'intéresse un peu à la représentation en mémoire d'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Ancetre
    {
    };
    class Parent : public Ancetre
    {
    };
    class AutreParent : public Ancetre
    {
    };
    class Fille : public Parent, public AutreParent
    {
    };
    on se rend compte que les classes Parent et AutreParent sont toutes les deux composées d'une représentation de la classe Ancetre et que la classe fille, qui est composée de Parent et de AutreParent sera donc composée d'une composante Ancetre venue de Parent et d'une composante Ancetre venue de AutreParent.

    Il est peu probable que cela nous intéresse d'avoir ces deux composantes car cela impliquerait que l'on peut modifier la composante Ancetre issue de Parent sans modifier la composante Ancetre issue de AutreParent et, pas de bol, se baser plus tard sur l'état de la composante Ancetre issue de AutreParent alors qu'elle ne reflète pas le même état que la composante Ancetre issue de Parent, qui, elle, est considérée comme "à jour".

    En déclarant virtuel l'héritage de Parent et de AutreParent envers Ancetre, on indique au compilateur qu'il risque, dans les classes dérivées, d'avoir plusieurs sources possibles pour la composante Ancêtre (typiquement parce qu'on fait hériter une classe Fille de Parent et de AutreParent, selon mon exemple ), mais qu'il ne doit pas créer plus d'une représentation de cette composante en mémoire.

    Quand tu crées une classe C qui hérite de manière virtuelle de A et de manière non virtuelle de B, tu indiques simplement au compilateur que les classes qui hériteront de C peuvent avoir plusieurs sources pour la composante A (parce qu'elles peuvent hériter de C et de... D qui hérite virtuellement de A), mais qu'il n'y aura jamais d'autre classe que C qui risque d'apporter la composante B.

    Si les flèches signifient "hérite publiquement de" tu pourrais donc avoir un shéma proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
            D------>A<-----C----->B
            ^              ^
            |              |
            |              |
            |-------E------|
    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

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    La FAQ est précise je trouve...
    Pas tant que ça, si on regarde la FAQ Parashift, et la première réponse sur ce fil de StackOverflow.

    Citation Envoyé par germinolegrand Voir le message
    Si D hérite de C il pourra choisir d'appeler lui-même le constructeur de A.
    Et s'il ne le fait pas, que se passe-t-il ?

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Hors de tout contexte, cela n'a pas beaucoup d'intérêt...
    En fait, je suis en train de rentrer dans le code d'un projet, et je la hiérarchie présentée est complète parce rapport à ce que j'ai trouvé dans ce code. Aucune classe n'hérite de C.

    Citation Envoyé par koala01 Voir le message
    Quand tu crées une classe C qui hérite de manière virtuelle de A et de manière non virtuelle de B, tu indiques simplement au compilateur que les classes qui hériteront de C peuvent avoir plusieurs sources pour la composante A (parce qu'elles peuvent hériter de C et de... D qui hérite virtuellement de A), mais qu'il n'y aura jamais d'autre classe que C qui risque d'apporter la composante B.
    Ça dénote une construction un peu tordue, non ?

    A noter que j'étais une fois tombé sur ce cas dans un test d'entretien.

  6. #6
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Je parlais de la FAQ DVP ^^
    Si ce n'est pas fait c'est dans le constructeur de C que c'est fait. Si c'était obligatoire, le compilateur l'indique par une erreur claire.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par oodini Voir le message
    Et s'il ne le fait pas, que se passe-t-il ?
    En fait, ce n'est pas que le concepteur d'une classe D peut choisir d'appeler lui-même le constructeur de la classe ancêtre, c'est surtout qu'il doit le faire, à moins qu'il n'y ait un constructeur par défaut...


    Citation Envoyé par oodini Voir le message
    En fait, je suis en train de rentrer dans le code d'un projet, et je la hiérarchie présentée est complète parce rapport à ce que j'ai trouvé dans ce code. Aucune classe n'hérite de C.
    Peut etre était il question, au début, de permettre un héritage de C et d'une autre classe dérivant de A...

    Soit, le concepteur de la classe C a simplement "prévu le coup" pour le cas où cela se produirait, soit il a, tout aussi simplement, changé d'avis pour une raison qui lui est propre.
    Ça dénote une construction un peu tordue, non ?
    Ca dénote surtout un problème de conception dans le sens où on peut se poser la question de la granularité correcte envisagée pour la classe ancêtre.

    Mais la construction n'est pas si tordue que cela, dans le sens où elle est régulièrement mise en oeuvre lorsqu'un projet fait un usage plus ou moins intensif d'un "god object":

    Si tu regardes certaines bibliothèques d'IHM comme la Vcl de borland, tu te rends compte que tout dérive, au final, d'une classe Object, mais que tu as certains héritages qui font que tu hérites de Sender et d'autre chose, toutes deux dérivant de Object

    Ceci dit, le problème repose plus sur le fait de vouloir pouvoir mettre "tout et n'importe quoi" dans une même collection (en les faisant connaitre comme des Object), mais c'est un autre débat, pour lequel les avis sont partagés et ont déjà fait couler beaucoup d'encre
    A noter que j'étais une fois tombé sur ce cas dans un test d'entretien.
    C'est normal, car c'est un cas "peau de banane" qui, en théorie du moins, permet de s'assurer que tu as bien assimilé les problèmes relatifs à l'héritage
    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

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Peut-être était il question, au début, de permettre un héritage de C et d'une autre classe dérivant de A...

    Soit, le concepteur de la classe C a simplement "prévu le coup" pour le cas où cela se produirait, soit il a, tout aussi simplement, changé d'avis pour une raison qui lui est propre.
    J'ai fini par trouver en interne un développeur au courant de la tambouille, et il m'a effectivement confirmé cela. En me précisant que cet héritage virtuel était dorénavant obsolète.

    Citation Envoyé par koala01 Voir le message
    C'est normal, car c'est un cas "peau de banane" qui, en théorie du moins, permet de s'assurer que tu as bien assimilé les problèmes relatifs à l'héritage
    C'est un peu pervers, car le mécanisme de l'héritage virtuel est très peu documenté, même dans le bouquin de Stroustrup, qui n'est pas clair sur le sujet, je trouve.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par oodini Voir le message
    C'est un peu pervers, car le mécanisme de l'héritage virtuel est très peu documenté, même dans le bouquin de Stroustrup, qui n'est pas clair sur le sujet, je trouve.
    N'oublies pas que l'héritage est un principe qui va beaucoup plus loin que le "simple" C++...

    C'est un principe de conception, ce fait qu'il est finalement applicable à tous les langages orientés objets.

    Le fait est que de nombreux langages (comme C# ou java) interdisent purement et simplement l'héritage multiple, pour des raisons qui leur sont propres (mais essentiellement du au fait que toute classe dérive d'office de Object, pour que le garbage collector puisse travailler avec).

    C++ est, finalement, l'un des rares langages qui permette l'héritage multiple, qui reste le seul cas où il est possible de se retrouver avec un héritage en losange

    Mais le principe reste le même dans tous les langages : si une classe B hérite d'une classe A, les objets de type B disposent, d'office, une "composante" de type A.

    C'est pour cette raison qu'il fallait trouver une solution pour éviter d'avoir plusieurs fois la composante "ancêtre" dans le cas particulier d'un héritage en losange.

    L'héritage virtuel est la solution trouvée par C++ pour résoudre ce problème, mais il n'est pas impossible que d'autres langages apportent d'autres solutions
    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

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par koala01 Voir le message
    C++ est, finalement, l'un des rares langages qui permette l'héritage multiple,
    Je crois que je connais plus de languages qui ont de l'heritage multiple (Common Lisp, Eiffel, Python, Dylan, Perl) que de language qui n'en n'ont pas (Oberon, SmallTalk, Simula), surtout si on ajoute les variantes plus ou moins bridees (interfaces: Java, C#, Ruby, Ada05, Mixin: scala).

    qui reste le seul cas où il est possible de se retrouver avec un héritage en losange
    La forme restreinte d'heritage multiple que sont les interfaces a la Java ne permet que la version en losange.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

Discussions similaires

  1. FlyPad -> Le Bloc-note virtuel [inscription non requise !]
    Par TheBananier dans le forum Mon site
    Réponses: 10
    Dernier message: 16/02/2009, 08h31
  2. Creation Hyperlink sur un dossier non virtuel du serveur
    Par predalpha dans le forum ASP.NET
    Réponses: 2
    Dernier message: 13/05/2008, 15h55
  3. Réponses: 7
    Dernier message: 20/12/2007, 15h13
  4. [Héritage] Downcasting et méthodes virtuelles
    Par poukill dans le forum C++
    Réponses: 8
    Dernier message: 16/07/2007, 13h38
  5. Réponses: 19
    Dernier message: 10/02/2005, 22h43

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