Mehrfachvererbung in C ++

Wenn ein C ++ Klasse von einer anderen erben kann, dann sofort stellt sich die Frage: "Kann eine Klasse erben von zwei (oder mehr) Klassen?" Die Antwort in eine unqualifizierte "Ja."

Menu

Es kann wertvoll sein, ein reales Beispiel der Mehrfachvererbung zu sehen, zu verstehen, warum dies eine Fähigkeit wert ist. Die meisten Universitäten bieten Arbeitsplätze Studenten als Tutoren zu absolvieren. Diese Personen sind noch Studenten und verfügen über alle Eigenschaften eines Studenten -, sondern darüber hinaus, sie sind auch die Eigenschaften eines Instruktors gewährt. So logisch, sieht ihre Vererbungsbaum wie folgt aus:

A & lt; span class =TeachingAssistant erbt von beiden Schüler "/>
EIN Lehrassistent erbt von beiden Schüler und Lehrer.

Ausgedrückt in C ++, dies würde wie folgt aussehen:

Klasse Schüler {public: double gpa () - bool einschreiben (Kurs) -bool Pay (Doppel-Dollar) -} - Klasse Instructor {public: Doppel Grad (Artifact) -bool (Kurs) lehren -bool GetPaid (Doppel-Dollar) -} -Klasse TeachingAssistant: public Student, öffentliche Instructor {public: Instructor Berater (Ausbilder) -Instructor Berater () -} -

Der einzige Unterschied zwischen diesem Beispiel und Beispiele für einfache Vererbung ist das Auftreten von zwei Klassennamen nach der Erklärung der Lehrassistent.

In Anbetracht der Klassendefinitionen nur gezeigt, die alle der folgenden kann gesagt werden:

TeachingAssistant ta - // erhalten eine Note wie ein studentdouble d = ta.gpa () - // Klasse ein Papier wie ein instructorta.grade (document) - // Ich kann eine ta an eine Funktion, die eine Studentvoid Partei erwartet (Student ) -Partei (ta) - // oder eine Funktion, die ein Instructorvoid Soiree (Ausbilder) -soiree (ta) erwartet -

So weit, ist es gut. Was ist, nicht über die Mehrfachvererbung zu mögen?

Mehrere Zweideutigkeiten

Überprüfen Schüler und Lehrer Klassen teilen sich diese beiden Klassen eine Eigenschaft: eine Universität zugewiesenen Identifikationsnummer. Aber wenn Sie versuchen, diese Eigenschaft wie folgt hinzufügen, erhalten Sie nichts anderes als Beschwerden von C ++:

Klasse Schüler {public: IntID () - Doppel gpa () - bool (Kurs) -bool Pay (Doppel Dollar) einschreiben -} - Klasse Instructor {public: int id () - Doppel-Grad (Artifact) lehren -bool (Kurs) -bool GetPaid (Doppel-Dollar) -} - Klasse TeachingAssistant: public Student, öffentliche Instructor {public: Instructor Berater (Ausbilder) -Instructor Berater () -

};

Dieses Problem wird grafisch dargestellt, hier:

Das Hinzufügen der & lt; span class =id () Eigenschaft sowohl Schüler und
das Hinzufügen der Ich würde() Eigenschaft sowohl Schüler und Lehrer führt zu Verwirrung.

Das Problem ist, dass jetzt, wenn Sie etwas sagen wie:

TeachingAssistant ta-cout lt; lt; "TA-ID ist" lt; lt; ta.id () - // denen id?

welche Ich würde() vorgesehen ist - derjenige, der Lehrassistent Abgeleitet von Schüler oder derjenige, der es erbt von Lehrer? Die Zweideutigkeit kann durch Angabe der Pfad zu lösen Ich würde (bekannt als qualifizierten Namen) so was:

cout lt; lt; "TA Schüler-ID ist" lt; lt; ta.Student :: id () -

Jetzt gibt es keine Zweideutigkeit. Durch die Basisklasse angibt, ist C ++, sagte die Ich würde() nehmen.

Die Lösung der Mehrdeutigkeit: Erster Versuch

Aber was, wenn die beiden Instanzen von Ich würde() sind nicht anders? Nehmen wir an, wie viele Universitäten, eine bestimmte Hochschule sowohl Studenten und Dozenten eine eindeutige Identifikationsnummer zuweist. In diesem Fall ist wollte, was wirklich ist die Situation in der folgenden Abbildung dargestellt: Jetzt ein Lehrassistent hat nur eine einzige Ich würde() Eigentum.

Die & lt; span class =id () Eigenschaft wird von einer Basisklasse, die für beide geerbt
Das Ich würde() Eigenschaft wird von einer Basisklasse, die für beide geerbt Schüler und Lehrer.

Um zu versuchen, diesen Zustand in C ++ zum Ausdruck bringen, dass das folgende geschrieben:

Klasse Academic {public: int id () -} - Klasse Student: public Academic {public: double gpa () - bool einschreiben (Kurs) -bool Pay (Doppel-Dollar) -} - Klasse Ausbilder: public Academic {public: Doppel Grad (Artefakt) -bool lehren (Kurs) -bool GetPaid (Doppel-Dollar) -} - Klasse TeachingAssistant: public Student, öffentliche Instructor {public: Instructor Berater (Ausbilder) -Instructor Berater () -} -

Leider (und recht überraschend), ist dieser Ansatz nicht das Problem überhaupt lösen. Ein Verweis auf ta.id () ist nach wie vor unklar. Es stellt sich heraus, dass dieser Code nicht mit dem vorhergehenden image- statt schafft, ist es, die Situation hier gezeigt erstellt:

Eine einzige Basisklasse kann in der Unterklasse mehrfach vererbt werden.
Eine einzige Basisklasse kann in der Unterklasse mehrfach vererbt werden.

Es scheint, dass Lehrassistent jetzt erbt akademisch zweimal - einmal durch seine Schüler-ness, und wieder durch seine Lehrer-ness. Es hat jetzt ein Student :: Academic :: id () und ein Ausbilder :: Academic :: id ().

Die Lösung der Mehrdeutigkeit

Um zu erreichen, was in C ++ in der dritten Figur dieses Artikels angezeigt wird, müssen Sie wieder auf etwas C ++ Anrufe fallen virtuelle Vererbung. Diese Funktion erscheint in Aktion wie folgt:

Klasse TeachingAssistant: virtuelle öffentliche Student, virtuellen öffentlichen Instructor {public: Instructor Berater (Ausbilder) -Instructor Berater () -} -

Die Verwendung des virtuell Stichwort sagt C ++ alle gängigen Basisklassen zu kombinieren, Schüler und Lehrer könnte teilen. Die folgenden nicht mehr generiert einen Compiler-Fehler:

cout lt; lt; "TA Schüler-ID ist" lt; lt; ta.id () - // kein Fehler jetzt

Mit virtuellen Vererbung, Lehrassistent erbt eine und nur eine Kopie akademisch und die Bezugnahme auf ta.id () ist nicht mehr eindeutig.

Menü