Weil besser als gut!

Vererbung (C++)Inhaltsverzeichnis AllgemeinesJede Klasse kann durch Vererbung (inheritance) ihre Eigenschaften (Attribute und Methoden) an neue Klassen weitergeben. Terminologie
Eigenschaften
ProgrammbeispielDies sei der Code der Basisklasse: C++ class Basis { string s; public: void setstr(string ss) { s = ss; } string getstr() { return s; } }; Dann kann mit diesem Code die Klasse abgeleitet werden: C++ class Sub : public Basis { int i; public: void seti(int ii) { i = ii; } int geti() { return i; } }; Dieses können wir jetzt folgendermaßen anwenden: C++ void main() { Sub obj; obj.setstr("Das Ergebnis ist: "); obj.seti(42); cout << obj.getstr() << obj.geti() << endl; } Dieses Programm erzeugt folgende Ausgabe: Das Ergebnis ist: 42 Merke: Subclassobjekt obj kennt Elemente der Klasse Basis und der Klasse Sub! public-, private-, protected- VererbungDie Elemente einer Basisklasse werden in der abgeleiteten Klasse offenbar übernommen. Welchen Zugriffsrechten sie in der subclass unterliegen, wird bei der Ableitung der subclass angegeben, z.B.: class Sub : public Basis oder class Sub : private Basis oder class Sub : protected Basis Darüber hinaus gibt es Standardwerte:
Regeln
BeispielIn diesem Beispiel (pubprivprot.cpp) werden die unterschiedlichen Arten der Vererbung aufgezeigt. Bemerkungen zu pubprivprot.cpp
Wozu dient eigentlich die Vererbung ?Die Sprache C++ stellt das Konstrukt 'Vererbung' in den drei genannten Variationen zur Verfügung. Zu welchem Zweck dieses Sprachmittel tatsächlich eingesetzt wird, bleibt letztlich dem Geschick der ProgrammiererIn überlassen. Auf den folgenden Seiten wird eine weitgehend etablierte Sichtweise dargestellt, dies soll aber ausdrücklich nicht als 'Evangelium' aufgefasst werden. public VererbungDies ist mit Abstand die häufigste Art der Vererbung, sie dient der Modellierung von Ist-Beziehungen:
Das Subclass Objekt ist auch ein Basisobjekt, denn alles was ein Basisobjekt kann, kann das Subobjekt ebenfalls. public abgeleitete Subclasses sind Spezialisierungen der Basisklasse: Subobjekte sind spezifischer, die Subclass fügt Elemente hinzu und erweitert so die Basisklasse um speziellere Methoden/Attribute. Aus Anwendungssicht ist die Subclass keine Einschränkung gegenüber der Basisklasse - die öffentliche Schnittstelle wird höchstens erweitert. liegen wirkliche Ist-Beziehungen vor, so entsteht eine Klassenhierarchie mit hohem Wiederverwendungsgrad - d.h. Code-Minimierung innerhalb der Klassenhierarchie selbst. Außerdem entstehen Klassen, die leicht von der AnwenderIn erweitert werden können und dienen so der Wiederverwendung (reuse). private VererbungAlle Elemente der Basisklasse werden privat, so dass die öffentliche Schnittstelle der Subclass gegenüber der Basisklassenschnittstelle eingeschränkt ist. Innerhalb der Subclass steht die öffentliche Schnittstelle der Basisklasse aber vollständig zur Verfügung. Aus äußerer Sicht hat die Subclass Eigenschaften verloren - sie stellt keine Spezialisierung mehr dar. durch private Vererbung kann daher keine Ist-Beziehung, wohl aber eine Hat-Beziehung abgebildet werden:
Geerbte Elemente werden gekapselt und stehen nur innerhalb der Subclass zur Verfügung, so dass hier eine Alternative zu Aggregaten gegeben ist. protected VererbungSie ist ähnlich der privaten Vererbung, aber: Geerbtes ist in der Subclass protected und kann weitervererbt werden. Die private Vererbung hingegen unterbricht die Vererbung der Basiselemente an weitere Generationen. Konstruktoren, InitialisierungWird ein Subclassobjekt instanziiert, so wird zuerst der Konstruktor der Basisklasse aufgerufen - noch vor Ausführung des eigenen Konstruktorrumpfs. Wurde über mehrere Generationen vererbt, so wird zuerst der innerste Konstruktor gerufen. Besitzen die Basisklassen einen Default Konstruktor, wird dieser automatisch ausgeführt, falls nicht anders angegeben. non-Default Konstruktoren müssen explizit in der Initialisierungsliste des Subclasskonstruktors aufgeführt werden. DestruktorenDestruktoren sind immer 'Default Destruktoren', da sie keine Parameter haben - sie werden entlang der Vererbungshierarchie automatisch aufgerufen. – werden dynamisch Elemente angelegt, so muss dennoch ein spezieller Destruktor geschrieben werden, der den Heap freigibt. Destruktoren werden in umgekehrter Reihenfolge der Konstruktoren aufgerufen, d.h. zuerst der Destruktor der Subclass, dann der Basisdestruktor. ZuweisungFür alle Klassen wird ein Default-Zuweisungsoperator bereitgestellt, der Objekte einer gemeinsamen Klasse verarbeitet:
Für Objekte abgeleiteter Klassen gilt, dass bei der Zuweisung von Subclassobjekten für den Basisklassenanteil automatisch der Zuweisungsoperator der Basisklasse aufgerufen wird. Sind dort Heapobjekte enthalten, müssen sie durch Überladung in der Basisklasse behandelt werden. da Subclassobjekte auch Basisklassenobjekte sind, ist die Zuweisung C++ basis_obj = sub_obj; immer möglich. Die spezifischen Attribute des sub_obj werden dabei natürlich nicht berücksichtigt. Die Umkehrung C++ sub_obj = basis_obj; RedefinitionHaben Elemente in der abgeleiteten Klasse den gleichen Bezeichner wie Elemente der Basisklasse, so nennt man dies Redefinition (Überdeckung). Dabei ist zu beachten:
Redefinition ist kein Overloading! Overloading findet im selben Gültigkeitsbereich statt, z.B. innerhalb einer Klasse. Überladene Funktionen werden anhand der Signatur unterschieden, ein redefiniertes Element verdeckt jedoch alle gleichnamigen Elemente der gesamten Klassenhierarche, unabhängig von ihrer Signatur. Sind Elemente in der Klassenhierarchie mehrfach redefiniert, so wird in der Hierarchie 'aufwärts' gesucht und das erste passende Element gewählt. |
Zahlen & Daten
Publish |