L'héritage multiple en C ++

Si une classe C ++ peut hériter d'une autre, alors la question se pose immédiatement, "Une classe peut hériter de deux (ou plusieurs) des classes?" La réponse en est une sans réserve "Oui."

Sommaire

Il peut être intéressant de voir un exemple dans le monde réel de l'héritage multiple de comprendre pourquoi il en est une capacité utile d'avoir. La plupart des universités offrent des emplois à des étudiants diplômés comme assistants d'enseignement. Ces individus sont encore étudiants et ont toutes les propriétés d'un étudiant -, mais, en plus, ils sont également accordées les caractéristiques d'un instructeur. Ainsi, logiquement, leur arbre d'héritage ressemble à ceci:

A & lt; span class =TeachingAssistant hérite de deux Étudiant "/>
UN TeachingAssistant hérite de deux Étudiant et Instructeur.

Exprimé en C ++, cela apparaîtra comme suit:

classe Étudiant {public: double-GPA () - bool inscrire (Cours) -bool salaire (en dollars doubles) -} - classe instructeur {public: à double niveau (artefact) -bool enseigner (bien sûr) -bool GetPaid (en dollars doubles) -} TeachingAssistant -class: Student publique, instructeur {public: conseiller instructeur (Instructeur) -Instructeur conseiller () -} -

La seule différence entre cet exemple et les exemples de l'héritage simple est l'apparition de deux noms de classe après la déclaration de TeachingAssistant.

Étant donné les définitions de classe vient de montrer, tout ce qui suit peut être dit:

TeachingAssistant ta - // obtenir une note comme un d studentdouble = ta.gpa () - // année un document comme un instructorta.grade (document) - // je peux passer un TA à une fonction qui attend un parti Studentvoid (étudiants ) à parti (ta) - // ou une fonction qui attend une soiree Instructorvoid (Instructeur) -soiree (ta) -

Jusqu'ici, tout va bien. Qu'est-ce qui ne pas aimer l'héritage multiple?

Ambiguïtés multiples

Examiner Étudiant et Instructeur les classes, deux de ces classes partagent une propriété: un numéro d'identification attribué à une université. Mais si vous essayez d'ajouter cette propriété comme suit, vous obtenez rien d'autre que des plaintes de C ++:




classe Étudiant {public: intid () - le double GPA () - bool inscrire (Cours) salaire -bool (dollars doubles) -} - Instructeur de classe {public: int id () - le double de qualité (artefact) -bool enseigner (cours) -bool GetPaid (dollars doubles) -} - TeachingAssistant de classe: Student publique, instructeur {public: conseiller instructeur (Instructeur) -Instructeur conseiller () -

};

Ce trouble est représentée graphiquement, ici:

Ajout de la section & lt; span class =id () la propriété à la fois Étudiant et
L'ajout de la id () la propriété à la fois Étudiant et Instructeur est source de confusion.

Le problème est que maintenant, quand vous dites quelque chose comme

TeachingAssistant ta-cout lt; lt; "Id TA est" lt; lt; ta.id () - // qui id?

laquelle id() est destiné - celui qui TeachingAssistant hérite de Étudiant ou celui qui hérite à partir de Instructeur? L'ambiguïté peut être résolu en spécifiant le chemin d'accès id (connue sous le nom nom qualifié) comme ça:

cout lt; lt; «Étudiant id TA est" lt; lt; ta.Student :: id () -

Maintenant, il n'y a aucune ambiguïté. En spécifiant la classe de base, C ++ est dit ce qui id () choisir.

Résoudre l'ambiguïté: Première tentative

Mais que faire si les deux instances de id () sont pas différent? Supposons que, comme beaucoup d'universités, une université donnée attribue un numéro d'identification unique pour les étudiants et instructeurs. Dans ce cas, ce qui est vraiment voulu la situation est montré dans l'image suivante: Maintenant, une TeachingAssistant mais a un seul id () propriété.

& Lt; span class =id () propriété est héritée de la classe de base commune à la fois
La id () propriété est héritée d'une classe de base commune à la fois Étudiant et Instructeur.

Pour essayer d'exprimer cet état de choses en C ++, supposons que la suivante est écrit:

classe académique {public: int id () -} - classe de l'élève: publique académique {public: double-GPA () - bool inscrire (Cours) salaire -bool (dollars doubles) -} - classe Instructeur: Academic {public: à double qualité (artefact) -bool enseigner (Cours) -bool GetPaid (dollars doubles) -} - classe TeachingAssistant: Student publique, instructeur {public: conseiller instructeur (Instructeur) -Instructeur conseiller () -} -

Malheureusement (et tout à fait surprenante), cette approche ne résout pas le problème du tout. Une référence à ta.id () est encore ambigu. Il se trouve que ce code ne crée pas l'image- précédente au lieu, il crée la situation représentée ici:

Une seule classe de base peut être héréditaire dans les sous-classes à plusieurs reprises.
Une seule classe de base peut être héréditaire dans les sous-classes à plusieurs reprises.

Il semble que TeachingAssistant hérite maintenant Academic deux fois - une fois à travers son Étudiant-Ness, et encore à travers son Instructeur-Ness. Il a maintenant une Étudiant :: :: académique id () Et un Instructeur :: :: académique id ().

Résoudre l'ambiguïté

Afin de parvenir à ce qui apparaît dans la troisième figure de cet article en C ++, vous devez rabattre sur les appels de quelque chose C héritage virtuel. Cette fonction apparaît dans l'action comme suit:

classe TeachingAssistant: Student public virtuel, instructeur public virtuel {public: conseiller instructeur (Instructeur) -Instructeur conseiller () -} -

L'utilisation de la virtuel mot-clé raconte C ++ de combiner toutes les classes de base communs qui Étudiant et Instructeur pourraient partager. Ce qui suit ne génère plus une erreur de compilation:

cout lt; lt; «Étudiant id TA est" lt; lt; ta.id () - // aucune erreur maintenant

Avec l'héritage virtuel, TeachingAssistant hérite et une seule copie de Academic et la référence à ta.id () est plus ambigu.


» » » » L'héritage multiple en C ++