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!

 

Vererbung (C++)

Allgemeines

Klassen_basis_ableitung_1.png

Jede Klasse kann durch Vererbung (inheritance) ihre Eigenschaften (Attribute und Methoden) an neue Klassen weitergeben.

Terminologie

alte Klasse
Basisklasse, base class, parent class, superclass
neue Klasse
abgeleitete Klasse, derived class, child class, subclass

Eigenschaften

  • in der abgeleiteten Klasse stehen alle Methoden und Attribute der Basisklasse zur Verfügung
  • in der abgeleiteten Klasse werden Eigenschaften hinzugefügt
  • Eigenschaften der Basisklasse können in der abgeleiteten Klasse nicht 'entfernt' werden

Programmbeispiel

Dies 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- Vererbung

Die 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:

  • für class: private
  • für struct: public

Regeln

  • private Elemente werden nicht vererbt (in der subclass nicht verfügbar)
  • public Vererbung: public und protected Elemente bleiben public / protected in der subclass
  • protected Vererbung: public und protected Elemente werden protected in der subclass
  • private Vererbung: public und protected Elemente werden private in der subclass

Beispiel

Klassen_vererbungsdiagramm.png

In diesem Beispiel (pubprivprot.cpp) werden die unterschiedlichen Arten der Vererbung aufgezeigt.

Bemerkungen zu pubprivprot.cpp

  • private Elemente werden niemals vererbt, auch nicht privat. Subclassobjekte können nur indirekt über Methoden darauf zugreifen (zeigSubPub() könnte z.B. zeigBasis() aufrufen, um das private Element priv auszugeben)
  • die globale Funktion main hat nur Zugriff auf public Elemente von Objekten der Basisklasse und public vererbten Klassen
  • die SubXX Objekte verhalten sich auf den ersten Blick ähnlich, aber:
    • SubPub_obj gewährt main Zugriff auf public Daten
    • SubPriv_obj hat alle Elemente (Attribute und Methode) private geerbt und kann davon nichts an SubSubPriv_obj weitergeben - die eigene public Methode aber schon.
  • jedes Subclassobjekt erbt seine eigene Instanz der Basisklassen

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 Vererbung

Dies ist mit Abstand die häufigste Art der Vererbung, sie dient der Modellierung von Ist-Beziehungen:

  • Baum ist eine Pflanze
  • Haus ist ein Gebäude
  • Segelboot ist ein Boot
  • ...

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 Vererbung

Alle 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:

  • Mensch hat Kopf
  • Team hat Mitarbeiter
  • Auto hat Räder
  • ...

Geerbte Elemente werden gekapselt und stehen nur innerhalb der Subclass zur Verfügung, so dass hier eine Alternative zu Aggregaten gegeben ist.

protected Vererbung

Sie 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, Initialisierung

Wird 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.

Destruktoren

Destruktoren 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.

Zuweisung

Für alle Klassen wird ein Default-Zuweisungsoperator bereitgestellt, der Objekte einer gemeinsamen Klasse verarbeitet:

  • alle Attribute werden elementweise kopiert
  • Heapobjekte werden nicht berücksichtigt, sie müssen gesondert behandelt werden (Operator überladen, Copy Konstruktor, etc.)

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;
ist nur möglich, wenn die subclass einen entsprechenden Operator bereitstellt.

Redefinition

Haben Elemente in der abgeleiteten Klasse den gleichen Bezeichner wie Elemente der Basisklasse, so nennt man dies Redefinition (Überdeckung). Dabei ist zu beachten:

  • Subclasselemente (Methoden und Attribute) verdecken die Elemente der Basisklasse (analog zur Verdeckung von Variablen in lokalen Blöcken).
  • mit dem Bereichsoperator :: kann auf die verdeckten Elemente zugegriffen werden.

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.

| Mehr

Zahlen & Daten

  • 592 Seitenaufrufe
  • 1110 Tage alt
  • 14 Versionen
  • Letzte Änderung: 13.05.2009 um 10:55 Uhr

Publish