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."
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:
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:
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é.
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:
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.