Was ist das hier?

  • Eine Plattform von Flensburger Studenten für Flensburger Studenten
  • Ein Wiki zum Sammeln von Wissen
  • Ein Forum zum Austausch
  • Eine Wissensdatenbank zum Informatikstudium:
    • Programmieren in C, C#, PHP, Javascript, HTML, CSS
    • Datenbanken und Abfragen mit SQL
    • 2D / 3D - Gestaltung
    • Mathe, Physik, Gerätetechnik, RoBs
    • Audio- / Videotechnik
    • ...und vieles mehr

Anmelden

Warum registrieren?

Weil besser als gut!

 

Mehrfachvererbung (C++)

Definition

OOP_Vererbung_Simple.png

Mehrfachvererbung (multiple inheritance) erlaubt, eine Klasse aus mehr als einer direkten Basisklasse abzuleiten. Syntaktisch ist dies zunächst einfach, die Basisklassen werden mit Angabe der jeweiligen Ableitungsart (public, private, protected) und mit Komma separiert aufgelistet:

C++
class AB : public A, public B
{
	...
};

Mehrdeutigkeiten

einfache Mehrdeutigkeiten

Durch identisch bezeichnete Elemente treten Mehrdeutigkeiten auf, die mit dem Bereichsoperator aufzulösen sind.

Sei in A und B je eine Methode machWatt() definiert, so können diese für ein Objekt ab der Klasse AB wie folgt aufgerufen werden:

C++
ab.A::machWatt();
ab.B::machWatt();

Der Aufruf ab.machWatt(); würde nicht kompiliert werden.

Alle eindeutig bezeichneten Elemente können natürlich direkt verwendet werden, denn ab ist ein Objekt der Klasse A und der Klasse B, besitzt also ein Subobjekt aus A und ein Subobjekt aus B.

mehrfach indirekte Basisklassen

OOP_Vererbung_Mehrfach.png

Es ist nicht möglich, dass eine Klasse direkt mehrfach als Basisklasse verwendet wird:

C++
class AB : public A, public B, public A
{
...
};

Indirekt ist dies sehr wohl möglich, in den allermeisten Fällen aber gar nicht erwünscht:

  • Basis ist mehrfach indirekte Basisklasse
  • alle AB Objekte erben indirekt zweifach aus Basis. Sie enthalten alle Basis-Elemente doppelt
  • auch diese Mehrdeutigkeiten müssen mit Angabe der Klasse, über die weitervererbt wurde (A bzw. B) und dem Bereichsoperator aufgelöst werden

virtuelle Basisklassen

OOP_Vererbung_Virtual.png

Virtuelle Basisklassen lösen das Problem der mehrfach indirekt vererbten Klassen. Die Bezeichnung virtuell ist hier unglücklich, dennoch wird auch hier das keyword virtual verwendet.

Kennzeichnet man bei der Deklaration der Klassen A und B die Basisklasse Basis als virtual, so entsteht ein anderes Vererbungsdiagramm (s. nächste Seite):

C++
class A : virtual public Basis { ... };
class B : virtual public Basis { ... };

Basis wird virtuelle Basisklasse, wenn die Klassen A und B sie als solche verwenden. Auswirkung hat dies aber erst für die Klasse AB: die Basis-Elemente sind jetzt nur noch einfach vorhanden.

zeigWatt() kann nun auf str direkt zugreifen, oder aber immer noch mit A::str oder B::str

Initialisierung

Normalerweise kann ein Konstruktor in seiner Initialisierungsliste nur Konstruktoren seiner direkten Basisklasse(n) auflisten. Parameter können so bis zur Initialisierungsliste der Basisklasse weitergereicht werden.

Ist die Basisklasse aber virtuell, entsteht wieder eine Mehrdeutigkeit: wer zuletzt seinen Wert 'durchreicht', hätte gewonnen - der Compiler lässt diese Situation natürlich nicht zu, es gelten folgende Sonderregeln:

Sonderregeln

Sonderregeln zur Initialisierung virtueller Basisklassen:

  • für virtuelle Basisklassen ist der Mechanismus des 'Weiterreichens' von Initialisierungswerten über Zwischenklassen deaktiviert
  • Konstruktoren virtueller Basisklassen können in Initialisierungslisten auch dann aufgeführt werden, wenn die virtuelle Basisklasse keine direkte Basisklasse ist
  • ist der Konstruktor der virtuellen Basisklasse nicht in der Liste aufgeführt, wird der Default-Konstruktor ausgeführt, sofern er existiert

Beispiel

Das Beispiel virtBasis.cpp

  • der 1. Konstruktor der Klasse AB darf Basis(s) in seiner Liste aufführen, da Basis virtuell ist
  • A(s) und B(s) in derselben Liste sind notwendig, da A und B keine Default Konstruktoren haben - Wirkung haben sie keine. Die Basis(s) Konstruktoraufrufe in den Listen von A und B sind ebenso wirkungslos, es sei denn, man instanziiert Objekte aus A oder B.
  • aktiviert man alternativ den auskommentierten Konstruktor, so wird der string nicht an Basis weitergereicht, sondern es wird der Default Konstruktor von Basis ausgeführt - str ist dann leer

virtuelle Methoden in virtuellen Basisklassen

Eine weitere Mehrdeutigkeit entsteht, wenn die Klassen A und B z.B. eine in Basis als virtuell deklarierte Methode f() implementieren. Da diese beiden Versionen von f() naturgemäß eine identische Signatur haben, sind sie in AB nur durch explizite Verwendung des Bereichsoperators zu unterscheiden.

Zweck der Mehrfachvererbung

Die Notwendigkeit der Mehrfachvererbung ist umstritten, eine Mehrfachvererbung erhöht die Komplexität eines Programms. Fast alle Probleme lassen sich auch ohne Mehrfachvererbung lösen (z.B. auch durch Aggregate, wenn die öffentliche Schnittstelle nicht weiter benötigt wird).

"Sie können sich MV als eine Eigenschaft der Programmiersprache 'von geringerer Bedeutung' vorstellen, die in Ihre täglichen Entscheidungen hinsichtlich des Entwurfs nicht einfließen sollte." (Bruce Eckel)

Häufiger als in anderen OOP-Sprachen entsteht in C++ der Bedarf an MV dadurch, dass C++ Klassenhierarchien i.A. keine gemeinsame Basis haben.

Andere Sprachen

In Smalltalk, Java und C# wird alles aus Object abgeleitet, so dass eine breite gemeinsame Basis immer gegeben ist. Ein 'Zusammensuchen' einzelner Eigenschaften durch MV ist oftmals nicht notwendig.

Reparatur

OOP_Vererbung_Schnittstellen_Reparatur.png

Eine anerkannt sinnvolle Verwendung der MV ist die Reparatur von Schnittstellen. Angenommen, Sie haben eine Klasse Segelboot erworben und möchten, dass Segelboote nun auch an der vorhandenen Hafensimulation teilnehmen. Dies ist aber nur für aus ContainerSchiff abgeleitete Klassen möglich.

Die MV erlaubt, diesen Mangel zu beheben, ohne die schon existierenden Klassen ändern zu müssen! Mit diesem Verfahren können auch andere Defekte nachträglich behoben werden, z.B. bei einer unvollkommenen Definition der abstrakten Basisklasse: kein virtueller Destruktor, bestimmte Methode ist nicht virtuell, Methode fehlt, etc.

| Mehr

Zahlen & Daten

  • 1649 Seitenaufrufe
  • 1087 Tage alt
  • 22 Versionen
  • Letzte Änderung: 28.05.2009 um 13:50 Uhr

Publish