Revision [aa161bd]
Letzte Änderung am 2020-05-26 07:59:56 durch Oksana Neopagitova
ADDITIONS
![image](/uploads/ObjProg06Vererbung/BMBF_Logo_klein.jpg?width=200)

## Objektorientierte Programmierung - Kapitel 6 - Vererbung

_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_


## 6.1. Grundbegriffe


#### Vererbung, abgeleitete Klasse, Basisklasse

Die <span style="text-decoration:underline;">Vererbung</span> ist ein effizienter Mechanismus, mit dem aus bereits existierenden Klassen neue Klassen gebildet werden können.
Die neue Klasse heißt <span style="text-decoration:underline;">abgeleitete Klasse</span> (Unterklasse).

Die alte Klasse heißt <span style="text-decoration:underline;">Basisklasse</span> (Oberklasse).

Jedes Objekt der abgeleiteten Klasse enthält ein anonymes Objekt der Basisklasse, welches als <span style="text-decoration:underline;">Teilobjekt</span> (Subobjekt) bezeichnet wird.

Die abgeleitete Klasse kann zusätzliche Attribute und Methoden enthalten. Diese Möglichkeit wird als <span style="text-decoration:underline;">Abweichung</span> (Erweiterung) bezeichnet.

![image](/uploads/ObjProg06Vererbung/oop29.gif?width=550)



#### class A

**Beispiel in C++**

%%(cpp)
{ private: int x;
>> public: int ma();
};

class B :public A
{ private: int y;
>> public: int mb();
};

main()
{ B b1;
}
%%

![image](/uploads/ObjProg06Vererbung/oop30.gif?width=200)



#### UML- Klassendiagramm

![image](/uploads/ObjProg06Vererbung/oop31.gif?width=400)



#### Zugriff auf Teilobjekt der Basisklasse

![image](/uploads/ObjProg06Vererbung/oop32.gif?width=500)



#### public- Vererbung

Bei der public- Vererbung steht die abgeleitete Klasse zur Basisklasse in einer Ist-Beziehung.

Ein Objekt b1 der abgeleitete Klasse B ist auch ein (spezielles) Objekt der Basisklasse A, weil b1 alle Methoden der Basisklasse A automatisch besitzt und sich so wie ein Objekt der Basisklasse A verhält.

![image](/uploads/ObjProg06Vererbung/oop33.gif?width=400)



#### Schnittstelle abgeleiteter Klasse

Die Deklarationen von allen public- Methoden bilden die öffentliche Schnittstelle (Interface). Durch diese Methoden kommuniziert ein Objekt mit der Umgebung.

Die öffentliche Schnittstelle der abgeleiteten Klasse besteht aus:

1) der öffentlichen Schnittstelle der Basisklasse und

2) den in der abgeleiteten Klasse zusätzlich deklarierten public-Methoden (und public- Attributen).



#### Vererbung der Schnittstelle

Die Schnittstelle der Basisklasse wird geerbt, wenn die öffentliche Methoden der Basisklasse durch Objekte der abgeleiteten Klasse aufgerufen werden dürfen.



#### Vererbung der Implementierung

Die Implementierung der Basisklasse wird geerbt, wenn öffentliche Methoden der Basisklasse zwar innerhalb der abgeleiteten Klasse aufgerufen werden dürfen. Der Code der Basisklasse wird dabei wiederverwendet.



#### Varianten der Vererbung

1) **Öffentliche Vererbung**
Vererbung von Schnittstelle und Implementierung.

%%(cpp)
class A{ };
class B :public A { };
%%
>>>>
2) **Private Vererbung**
Reine Vererbung derImplementierung.
>>
%%(cpp)
class A{ };
class B :private A { };
%%

3) **Einfache Vererbung**
Eine Klasse erbt von einer anderen Klasse.

%%(cpp)
class A{ };
class B :public A { };
%%

4) **Mehrfachvererbung**
Eine Klasse erbt von mehreren Klassen.

%%(cpp)
class A{ }; class B{ };
class C :public A, public B { };
%%


<span style="text-decoration:underline;">Klassenhierarchie </span>ist ein Satz von verwandten Klassen.

**Beispiel:**
>>
>>> class A{ };
>>> class B :public A { };
>>> class C :public A { };
>>>
<span style="text-decoration:underline;">Generalisierung </span>(Abstraktion) ist die Entwicklung der Basisklasse durch die Zusammenfassung von ähnlichen Eigenschaften und Verhaltensweisen (Attribute und Methoden) der vielen abgeleiteten Klassen.

a) Die Basisklasse ist eine Generalisierung der abgeleiteten Klassen.
b) In der Klassenhierarchie bedeutet das die Richtung nach oben.


<span style="text-decoration:underline;">Spezialisierung </span>(Konkretisierung) ist die Entwicklung der abgeleiteten Klasse durch die Ergänzung der Basisklasse mit der zusätzlichen Eigenschaften und Verhaltensweisen.

a) Die abgeleitete Klasse ist eine Spezialisierung der Basisklasse.
b) In der Klassenhierarchie bedeutet das die Richtung nach unten.

&rArr; Demo 1



#### Vorteile der Vererbung

1) **Datenabstraktion**
Allgemeine Eigenschaften und Vorgänge können mit Oberbegriffen versehen werden (Basisklassen).
Komplexe Sachverhalte werden dadurch einfacher darstellbar. Einige Klassen sind sehr kompliziert aufgebaut, besitzen aber eine einfache Schnittstelle.

2) **Wiederverwendbarkeit**
Bereits erstellte und ausgetestete Klassen können weiterhin verwendet und an neue Anforderungen angepasst werden. Dazu braucht nicht die Implementierung der Basisklasse, sondern nur ihre öffentliche Schnittstelle bekannt zu sein.



## 6.2. Einfache Vererbung


#### Aufbau des Objektes abgeleiteter Klasse

Alle Konstruktoren einer abgeleiteten Klasse müssen neu definiert werden. Sonst existieren nur Standard-Konstruktoren.

Bei der Initialisierung eines Objektes, welches Teilobjekt der Basisklasse enthält, sind mehrere Konstruktoren auszuführen.

**Reihenfolge der Konstruktor- Aufrufe:**

1) Konstruktor der Basisklasse. Ohne weitere Angabenwird der Default- Konstruktor aufgerufen.
2) Konstruktoren für alle Attribute-Objekte.
3) Konstruktor der abgeleiteten Klasse.
>>>>
&rArr; Demo 2



#### Aufbau des Teilobjektes

Der Aufruf von Default-Konstruktoren beim Aufbau von Teilobjekten hat folgende Nachteile:

1) Ein Teilobjekt der Basisklasse wird zwei mal mit Werten versehen:
>> a) zuerst durch den Aufruf des Default-Konstruktors der Basisklasse,
>> b) danach durch die Zuweisung beim Aufruf des Konstruktors der abgeleiteten Klasse. Diese doppelte Aktion beeinträchtigt die Ausführungszeit.

2) Die private- Attribute der Basisklasse werden durch Aufrufe der entsprechenden Zugriffsmethoden mit richtigen Anfangswerten versehen.

3) Konstante Objekte können nicht durch die Zuweisung mit Werten versehen werden.

4) Eine Klasse ohne Default-Konstruktor kann nicht als Basisklasse verwendet werden.



#### Zugriffsmethoden

Zugriffsmethoden gewährleisten den kontrollierten Zugriff auf die geschützten Attribute des Objektes.

%%(cpp)
class A {
>>private: int zet;
>>public: void setZet(int z) { _eventuelle Kontrolle
>>>zet = z;
>>}
};

main () {
>>A a1;
>>a1.zet = 5;_ Fehler
>>a1.setZet(5); _OK
}
%%



#### Basisinitialisierer

Ein Basisinitialisierer dient für den Aufruf eines Konstruktors der Basisklasse und wird in der Initialisierungsliste angegeben.

![image](/uploads/ObjProg06Vererbung/oop33.gif?width=500)

&rArr; Demo 3
&rArr; Demo 4


Eine Redefinition ist die Definition einer Methode in der abgeleiteten Klasse, wenn die Basisklasse eine Methode mit gleichem Namen hat. Durch Redefinition werden die Methoden an die neuen Fähigkeiten der Klasse angepasst.

Bei einer Redefinition darf die Signatur und der Rückgabe-Typ beider Methoden verschieden sein. Eine Überladung von Methoden findet dabei nicht statt, da die abgeleitete Klasse einen neuen Geltungsbereich besitzt.

Der Compiler sucht den Namen einer öffentlichen aufzurufenden Methode zunächst in der abgeleiteten Klasse.
Findet er diesen nicht, so geht er in der Klassenhierarchie eine Stufe höher. Dank diesem Such-Verfahren wird eine Methode der Basisklasse durch die neue redefinierte Methode verdeckt.

%%(cpp)
class A
{
>>public: void m();
};

class B : public A
{
>>public: void m(int );
};

main ()
{
>>B b1;
>>b1.A::m( );
}
%%

Es gibt zwei Möglichkeiten für die Implementierung der neuen redefinierten Methode der abgeleitete Klasse:

1) komplette Neuimplementierung,
2) Aufruf der verdeckten Methode der Basisklasse mit anschließender Ergänzung.

%%(cpp)
class A
>>{
>>>public: void m();
>>};

>>class B : public A
>>{
>>>public: void m(int )
>>>{
>>>>A::m(); &#8230; ;
>>>}
>>};
%%

&rArr; Demo 5



#### Abgeleitete Klasse mit eigenen Heapdaten


Wenn die abgeleitete Klasse selbst dynamischen Daten im Heap verwaltet, dann sind folgende Methoden selbst zu definieren:

1) einen Konstruktor (oder mehrere Konstruktoren),
2) einen Destruktor,
3) einen Kopierkonstruktor und
4) einen Zuweisungsoperator.

Ein selbstdefinierter Kopierkonstruktor muss den Kopierkonstruktor der Basisklasse explizit aufrufen. Sonst wird nur Default-Konstruktor der Basisklasse automatisch aufgerufen. ´

class B :public A
{
>>B(const B & alt) :A(alt){ &#8230; }
};

Ein selbstdefinierter Zuweisungsoperator muss den Zuweisungsoperator der Basisklasse explizit aufrufen.

class B :public A
{
>>B& B::operator=(const B & alt)
>>>> {
>>>> &#8230; ;
>>>> A::operator=(alt);
>>>> &#8230; ;
>>>> }
};

&rArr; Demo 6
&rArr; Demo 7



#### Vererbung von Zugriffsrechten

Das Zugriffsrecht des Basisklasse-Elementes in der abgeleiteten Klasse:

![image](/uploads/ObjProg06Vererbung/oop35.gif?width=500)

<span style="text-decoration:underline;">protected</span>-Attribute und Methoden sind in der eigenen und in der abgeleiteten Klassen zugreifbar, nicht aber in anderen Klassen oder außerhalb der Klasse.

&rArr; Demo 8



#### private- und protected- Vererbung

In beiden Fällen ist es notwendig, in der abgeleiteten Klasse völlig neue Schnittstelle zu definieren. Ein Objekt vom Typ der abgeleiteten Klasse ist damit kein spezielles Objekt der Basisklasse. Die Ist-Beziehung geht verloren.

class A
{
>>public: int ma();
};
class B : private A{};

main()
{
>>B b1;
>> b1.ma();_ Fehler
}

Zur Implementierung der neuen Methoden kann bereits vorhandener Code aus der Basisklasse verwendet werden (Implementierungsvererbung).



#### Wiederverwendung

Eine Klasse kann verwendet werden, um neue Objekte zu definieren.

class A{};
main(){ A a1;}

Eine Klasse kann wiederverwendet werden, um neue Klassen zu definieren:

1) Eine Klasse wird wiederverwendet, indem Objekte dieser Klasse als Attribute in anderen Klassen benutzt werden.

class A{};
class B{ A a1;};

2) Wiederverwendung durch Vererbung.

class A{}; class B :public A{};



#### Zwei Formen der Wiederverwendung

<table class="data" width="80%">
<tr>
<td>
<b>
durch Attribut
</b>
</td>
<td>
<b>
durch Vererbung
</b>
</td>
</tr>
<tr>
<td>
class A{}; <br/>
class B{ public: A a1;}; <br/>
class B{ private: A a1;};
</td>
<td>
class A{}; <br/>
class B :public A{}; <br/>
class B :private A{};
</td>
</tr>
<tr>
<td>
Elementinitialisierer für
unlösbares Teilobjekt a1:<br/>
B::B(A a):a1(a){}
</td>
<td>
Basisinitialisierer für
namenloses Teilobjekt:<br/>
B::B(A a):A(a){}
</td>
</tr>
<tr>
<td>
Objekt-Beziehung,
Hat-Beziehung,
has_a-Beziehung,
Aggregation, Komposition,
Horizontale
Wiederverwendung
</td>
<td>
Klassen-Beziehung,
Ist-Beziehung,
is_a-Beziehung,
Spezialisierung,
Vertikale
Wiederverwendung
>>></td>
>></tr>
</table>



## 6.3. Mehrfachvererbung
DELETIONS
![image](/uploads/ObjProg06Vererbung/BMBF_Logo_klein.jpg?width=200)
# Objektorientierte Programmierung - Kapitel 6 - Vererbung
_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_
## 6.1. Grundbegriffe
#### Vererbung, abgeleitete Klasse, Basisklasse

Die <span style="text-decoration:underline;">Vererbung</span> ist ein effizienter Mechanismus, mit dem aus bereits existierenden Klassen neue Klassen gebildet werden können.
Die neue Klasse heißt <span style="text-decoration:underline;">abgeleitete Klasse</span> (Unterklasse).

Die alte Klasse heißt <span style="text-decoration:underline;">Basisklasse</span> (Oberklasse).

Jedes Objekt der abgeleiteten Klasse enthält ein anonymes Objekt der Basisklasse, welches als <span style="text-decoration:underline;">Teilobjekt</span> (Subobjekt) bezeichnet wird.

Die abgeleitete Klasse kann zusätzliche Attribute und Methoden enthalten. Diese Möglichkeit wird als <span style="text-decoration:underline;">Abweichung</span> (Erweiterung) bezeichnet.
![image](/uploads/ObjProg06Vererbung/oop29.gif?width=550)
#### class A
**Beispiel in C++**
%%(cpp)
{ private: int x;
>> public: int ma();
};

class B :public A
{ private: int y;
>> public: int mb();
};

main()
{ B b1;
}
%%
![image](/uploads/ObjProg06Vererbung/oop30.gif?width=200)
#### UML- Klassendiagramm
![image](/uploads/ObjProg06Vererbung/oop31.gif?width=400)
#### Zugriff auf Teilobjekt der Basisklasse
![image](/uploads/ObjProg06Vererbung/oop32.gif?width=500)
#### public- Vererbung

Bei der public- Vererbung steht die abgeleitete Klasse zur Basisklasse in einer Ist-Beziehung.

Ein Objekt b1 der abgeleitete Klasse B ist auch ein (spezielles) Objekt der Basisklasse A, weil b1 alle Methoden der Basisklasse A automatisch besitzt und sich so wie ein Objekt der Basisklasse A verhält.
![image](/uploads/ObjProg06Vererbung/oop33.gif?width=400)
#### Schnittstelle abgeleiteter Klasse

Die Deklarationen von allen public- Methoden bilden die öffentliche Schnittstelle (Interface). Durch diese Methoden kommuniziert ein Objekt mit der Umgebung.

Die öffentliche Schnittstelle der abgeleiteten Klasse besteht aus:

1) der öffentlichen Schnittstelle der Basisklasse und

2) den in der abgeleiteten Klasse zusätzlich deklarierten public-Methoden (und public- Attributen).

#### Vererbung der Schnittstelle

Die Schnittstelle der Basisklasse wird geerbt, wenn die öffentliche Methoden der Basisklasse durch Objekte der abgeleiteten Klasse aufgerufen werden dürfen.

#### Vererbung der Implementierung

Die Implementierung der Basisklasse wird geerbt, wenn öffentliche Methoden der Basisklasse zwar innerhalb der abgeleiteten Klasse aufgerufen werden dürfen. Der Code der Basisklasse wird dabei wiederverwendet.

#### Varianten der Vererbung
1) **Öffentliche Vererbung**
Vererbung von Schnittstelle und Implementierung.
%%(cpp)
class A{ };
class B :public A { };
%%
>>>>
2) **Private Vererbung**
Reine Vererbung derImplementierung.
>>
%%(cpp)
class A{ };
class B :private A { };
%%

3) **Einfache Vererbung**
Eine Klasse erbt von einer anderen Klasse.
%%(cpp)
class A{ };
class B :public A { };
%%
4) **Mehrfachvererbung**
Eine Klasse erbt von mehreren Klassen.
%%(cpp)
class A{ }; class B{ };
class C :public A, public B { };
%%
<span style="text-decoration:underline;">Klassenhierarchie </span>ist ein Satz von verwandten Klassen.
**Beispiel:**
>>
>>> class A{ };
>>> class B :public A { };
>>> class C :public A { };
>>>
<span style="text-decoration:underline;">Generalisierung </span>(Abstraktion) ist die Entwicklung der Basisklasse durch die Zusammenfassung von ähnlichen Eigenschaften und Verhaltensweisen (Attribute und Methoden) der vielen abgeleiteten Klassen.

a) Die Basisklasse ist eine Generalisierung der abgeleiteten Klassen.
b) In der Klassenhierarchie bedeutet das die Richtung nach oben.

<span style="text-decoration:underline;">Spezialisierung </span>(Konkretisierung) ist die Entwicklung der abgeleiteten Klasse durch die Ergänzung der Basisklasse mit der zusätzlichen Eigenschaften und Verhaltensweisen.

a) Die abgeleitete Klasse ist eine Spezialisierung der Basisklasse.
b) In der Klassenhierarchie bedeutet das die Richtung nach unten.

&rArr; Demo 1
#### Vorteile der Vererbung

1) **Datenabstraktion**
Allgemeine Eigenschaften und Vorgänge können mit Oberbegriffen versehen werden (Basisklassen).
Komplexe Sachverhalte werden dadurch einfacher darstellbar. Einige Klassen sind sehr kompliziert aufgebaut, besitzen aber eine einfache Schnittstelle.

2) **Wiederverwendbarkeit**
Bereits erstellte und ausgetestete Klassen können weiterhin verwendet und an neue Anforderungen angepasst werden. Dazu braucht nicht die Implementierung der Basisklasse, sondern nur ihre öffentliche Schnittstelle bekannt zu sein.
## 6.2. Einfache Vererbung
#### Aufbau des Objektes abgeleiteter Klasse

Alle Konstruktoren einer abgeleiteten Klasse müssen neu definiert werden. Sonst existieren nur Standard-Konstruktoren.

Bei der Initialisierung eines Objektes, welches Teilobjekt der Basisklasse enthält, sind mehrere Konstruktoren auszuführen.

**Reihenfolge der Konstruktor- Aufrufe:**

1) Konstruktor der Basisklasse. Ohne weitere Angabenwird der Default- Konstruktor aufgerufen.
2) Konstruktoren für alle Attribute-Objekte.
3) Konstruktor der abgeleiteten Klasse.
>>>>
&rArr; Demo 2
#### Aufbau des Teilobjektes

Der Aufruf von Default-Konstruktoren beim Aufbau von Teilobjekten hat folgende Nachteile:

1) Ein Teilobjekt der Basisklasse wird zwei mal mit Werten versehen:
>> a) zuerst durch den Aufruf des Default-Konstruktors der Basisklasse,
>> b) danach durch die Zuweisung beim Aufruf des Konstruktors der abgeleiteten Klasse. Diese doppelte Aktion beeinträchtigt die Ausführungszeit.
2) Die private- Attribute der Basisklasse werden durch Aufrufe der entsprechenden Zugriffsmethoden mit richtigen Anfangswerten versehen.
3) Konstante Objekte können nicht durch die Zuweisung mit Werten versehen werden.
4) Eine Klasse ohne Default-Konstruktor kann nicht als Basisklasse verwendet werden.
#### Zugriffsmethoden

Zugriffsmethoden gewährleisten den kontrollierten Zugriff auf die geschützten Attribute des Objektes.

%%(cpp)
class A {
>>private: int zet;
>>public: void setZet(int z) { _eventuelle Kontrolle
>>>zet = z;
>>}
};

main () {
>>A a1;
>>a1.zet = 5;_ Fehler
>>a1.setZet(5); _OK
}
%%
#### Basisinitialisierer

Ein Basisinitialisierer dient für den Aufruf eines Konstruktors der Basisklasse und wird in der Initialisierungsliste angegeben.

![image](/uploads/ObjProg06Vererbung/oop33.gif?width=500)
&rArr; Demo 3
&rArr; Demo 4

Eine Redefinition ist die Definition einer Methode in der abgeleiteten Klasse, wenn die Basisklasse eine Methode mit gleichem Namen hat. Durch Redefinition werden die Methoden an die neuen Fähigkeiten der Klasse angepasst.

Bei einer Redefinition darf die Signatur und der Rückgabe-Typ beider Methoden verschieden sein. Eine Überladung von Methoden findet dabei nicht statt, da die abgeleitete Klasse einen neuen Geltungsbereich besitzt.
Der Compiler sucht den Namen einer öffentlichen aufzurufenden Methode zunächst in der abgeleiteten Klasse.
Findet er diesen nicht, so geht er in der Klassenhierarchie eine Stufe höher. Dank diesem Such-Verfahren wird eine Methode der Basisklasse durch die neue redefinierte Methode verdeckt.
%%(cpp)
class A
{
>>public: void m();
};
class B : public A
{
>>public: void m(int );
};
main ()
{
>>B b1;
>>b1.A::m( );
}
%%
Es gibt zwei Möglichkeiten für die Implementierung der neuen redefinierten Methode der abgeleitete Klasse:

1) komplette Neuimplementierung,
2) Aufruf der verdeckten Methode der Basisklasse mit anschließender Ergänzung.
%%(cpp)
class A
>>{
>>>public: void m();
>>};

>>class B : public A
>>{
>>>public: void m(int )
>>>{
>>>>A::m(); &#8230; ;
>>>}
>>};
%%
&rArr; Demo 5
#### Abgeleitete Klasse mit eigenen Heapdaten


Wenn die abgeleitete Klasse selbst dynamischen Daten im Heap verwaltet, dann sind folgende Methoden selbst zu definieren:

1) einen Konstruktor (oder mehrere Konstruktoren),
2) einen Destruktor,
3) einen Kopierkonstruktor und
4) einen Zuweisungsoperator.

Ein selbstdefinierter Kopierkonstruktor muss den Kopierkonstruktor der Basisklasse explizit aufrufen. Sonst wird nur Default-Konstruktor der Basisklasse automatisch aufgerufen. ´
class B :public A
{
>>B(const B & alt) :A(alt){ &#8230; }
};

Ein selbstdefinierter Zuweisungsoperator muss den Zuweisungsoperator der Basisklasse explizit aufrufen.
class B :public A
{
>>B& B::operator=(const B & alt)
>>>> {
>>>> &#8230; ;
>>>> A::operator=(alt);
>>>> &#8230; ;
>>>> }
};
&rArr; Demo 6
&rArr; Demo 7
#### Vererbung von Zugriffsrechten
Das Zugriffsrecht des Basisklasse-Elementes in der abgeleiteten Klasse:
![image](/uploads/ObjProg06Vererbung/oop35.gif?width=500)
<span style="text-decoration:underline;">protected</span>-Attribute und Methoden sind in der eigenen und in der abgeleiteten Klassen zugreifbar, nicht aber in anderen Klassen oder außerhalb der Klasse.

&rArr; Demo 8
#### private- und protected- Vererbung

In beiden Fällen ist es notwendig, in der abgeleiteten Klasse völlig neue Schnittstelle zu definieren. Ein Objekt vom Typ der abgeleiteten Klasse ist damit kein spezielles Objekt der Basisklasse. Die Ist-Beziehung geht verloren.
class A
{
>>public: int ma();
};
class B : private A{};
main()
{
>>B b1;
>> b1.ma();_ Fehler
}
Zur Implementierung der neuen Methoden kann bereits vorhandener Code aus der Basisklasse verwendet werden (Implementierungsvererbung).
#### Wiederverwendung

Eine Klasse kann verwendet werden, um neue Objekte zu definieren.
class A{};
main(){ A a1;}

Eine Klasse kann wiederverwendet werden, um neue Klassen zu definieren:

1) Eine Klasse wird wiederverwendet, indem Objekte dieser Klasse als Attribute in anderen Klassen benutzt werden.
class A{};
class B{ A a1;};

2) Wiederverwendung durch Vererbung.
class A{}; class B :public A{};

#### Zwei Formen der Wiederverwendung
<table class="data" width="80%">
>><tr>
>>><td>
>>>><b>
>>>>>durch Attribut
>>>></b>
>>></td>
>>><td>
>>>><b>
>>>>>durch Vererbung
>>>></b>
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>class A{}; <br/>
class B{ public: A a1;}; <br/>
class B{ private: A a1;};
>>></td>
>>><td>
>>>> class A{}; <br/>
class B :public A{}; <br/>
class B :private A{};
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>Elementinitialisierer für
unlösbares Teilobjekt a1:<br/>
B::B(A a):a1(a){}
>>></td>
>>><td>
>>>> Basisinitialisierer für
namenloses Teilobjekt:<br/>
B::B(A a):A(a){}
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>Objekt-Beziehung,
Hat-Beziehung,
has_a-Beziehung,
Aggregation, Komposition,
Horizontale
Wiederverwendung
>>></td>
>>><td>
>>>> Klassen-Beziehung,
Ist-Beziehung,
is_a-Beziehung,
Spezialisierung,
Vertikale
Wiederverwendung
>>></td>
>></tr>
</table>
## 6.3. Mehrfachvererbung
***
CategoryObjektorientierteProgrammierung
Revision [3ef13cf]
Bearbeitet am 2017-08-16 15:17:34 von ClaudiaMichel
ADDITIONS
CategoryObjektorientierteProgrammierung
DELETIONS
CategoryDelete
Revision [b425054]
Bearbeitet am 2016-09-27 12:42:20 von NicoleHennemann
ADDITIONS
CategoryDelete
DELETIONS
CategoryObjProg
Revision [aff066b]
Die älteste bekannte Version dieser Seite wurde von RonnyGertler am 2013-04-29 20:31:14 erstellt
ADDITIONS
![image](/uploads/ObjProg06Vererbung/BMBF_Logo_klein.jpg?width=200)
# Objektorientierte Programmierung - Kapitel 6 - Vererbung
_<span class="right">Inhalte von Dr. E. Nadobnyh</p>_
## 6.1. Grundbegriffe
#### Vererbung, abgeleitete Klasse, Basisklasse

Die <span style="text-decoration:underline;">Vererbung</span> ist ein effizienter Mechanismus, mit dem aus bereits existierenden Klassen neue Klassen gebildet werden können.
Die neue Klasse heißt <span style="text-decoration:underline;">abgeleitete Klasse</span> (Unterklasse).

Die alte Klasse heißt <span style="text-decoration:underline;">Basisklasse</span> (Oberklasse).

Jedes Objekt der abgeleiteten Klasse enthält ein anonymes Objekt der Basisklasse, welches als <span style="text-decoration:underline;">Teilobjekt</span> (Subobjekt) bezeichnet wird.

Die abgeleitete Klasse kann zusätzliche Attribute und Methoden enthalten. Diese Möglichkeit wird als <span style="text-decoration:underline;">Abweichung</span> (Erweiterung) bezeichnet.
![image](/uploads/ObjProg06Vererbung/oop29.gif?width=550)
#### class A
**Beispiel in C++**
%%(cpp)
{ private: int x;
>> public: int ma();
};

class B :public A
{ private: int y;
>> public: int mb();
};

main()
{ B b1;
}
%%
![image](/uploads/ObjProg06Vererbung/oop30.gif?width=200)
#### UML- Klassendiagramm
![image](/uploads/ObjProg06Vererbung/oop31.gif?width=400)
#### Zugriff auf Teilobjekt der Basisklasse
![image](/uploads/ObjProg06Vererbung/oop32.gif?width=500)
#### public- Vererbung

Bei der public- Vererbung steht die abgeleitete Klasse zur Basisklasse in einer Ist-Beziehung.

Ein Objekt b1 der abgeleitete Klasse B ist auch ein (spezielles) Objekt der Basisklasse A, weil b1 alle Methoden der Basisklasse A automatisch besitzt und sich so wie ein Objekt der Basisklasse A verhält.
![image](/uploads/ObjProg06Vererbung/oop33.gif?width=400)
#### Schnittstelle abgeleiteter Klasse

Die Deklarationen von allen public- Methoden bilden die öffentliche Schnittstelle (Interface). Durch diese Methoden kommuniziert ein Objekt mit der Umgebung.

Die öffentliche Schnittstelle der abgeleiteten Klasse besteht aus:

1) der öffentlichen Schnittstelle der Basisklasse und

2) den in der abgeleiteten Klasse zusätzlich deklarierten public-Methoden (und public- Attributen).

#### Vererbung der Schnittstelle

Die Schnittstelle der Basisklasse wird geerbt, wenn die öffentliche Methoden der Basisklasse durch Objekte der abgeleiteten Klasse aufgerufen werden dürfen.

#### Vererbung der Implementierung

Die Implementierung der Basisklasse wird geerbt, wenn öffentliche Methoden der Basisklasse zwar innerhalb der abgeleiteten Klasse aufgerufen werden dürfen. Der Code der Basisklasse wird dabei wiederverwendet.

#### Varianten der Vererbung
1) **Öffentliche Vererbung**
Vererbung von Schnittstelle und Implementierung.
%%(cpp)
class A{ };
class B :public A { };
%%
>>>>
2) **Private Vererbung**
Reine Vererbung derImplementierung.
>>
%%(cpp)
class A{ };
class B :private A { };
%%

3) **Einfache Vererbung**
Eine Klasse erbt von einer anderen Klasse.
%%(cpp)
class A{ };
class B :public A { };
%%
4) **Mehrfachvererbung**
Eine Klasse erbt von mehreren Klassen.
%%(cpp)
class A{ }; class B{ };
class C :public A, public B { };
%%
<span style="text-decoration:underline;">Klassenhierarchie </span>ist ein Satz von verwandten Klassen.
**Beispiel:**
>>
>>> class A{ };
>>> class B :public A { };
>>> class C :public A { };
>>>
<span style="text-decoration:underline;">Generalisierung </span>(Abstraktion) ist die Entwicklung der Basisklasse durch die Zusammenfassung von ähnlichen Eigenschaften und Verhaltensweisen (Attribute und Methoden) der vielen abgeleiteten Klassen.

a) Die Basisklasse ist eine Generalisierung der abgeleiteten Klassen.
b) In der Klassenhierarchie bedeutet das die Richtung nach oben.

<span style="text-decoration:underline;">Spezialisierung </span>(Konkretisierung) ist die Entwicklung der abgeleiteten Klasse durch die Ergänzung der Basisklasse mit der zusätzlichen Eigenschaften und Verhaltensweisen.

a) Die abgeleitete Klasse ist eine Spezialisierung der Basisklasse.
b) In der Klassenhierarchie bedeutet das die Richtung nach unten.

&rArr; Demo 1
#### Vorteile der Vererbung

1) **Datenabstraktion**
Allgemeine Eigenschaften und Vorgänge können mit Oberbegriffen versehen werden (Basisklassen).
Komplexe Sachverhalte werden dadurch einfacher darstellbar. Einige Klassen sind sehr kompliziert aufgebaut, besitzen aber eine einfache Schnittstelle.

2) **Wiederverwendbarkeit**
Bereits erstellte und ausgetestete Klassen können weiterhin verwendet und an neue Anforderungen angepasst werden. Dazu braucht nicht die Implementierung der Basisklasse, sondern nur ihre öffentliche Schnittstelle bekannt zu sein.
## 6.2. Einfache Vererbung
#### Aufbau des Objektes abgeleiteter Klasse

Alle Konstruktoren einer abgeleiteten Klasse müssen neu definiert werden. Sonst existieren nur Standard-Konstruktoren.

Bei der Initialisierung eines Objektes, welches Teilobjekt der Basisklasse enthält, sind mehrere Konstruktoren auszuführen.

**Reihenfolge der Konstruktor- Aufrufe:**

1) Konstruktor der Basisklasse. Ohne weitere Angabenwird der Default- Konstruktor aufgerufen.
2) Konstruktoren für alle Attribute-Objekte.
3) Konstruktor der abgeleiteten Klasse.
>>>>
&rArr; Demo 2
#### Aufbau des Teilobjektes

Der Aufruf von Default-Konstruktoren beim Aufbau von Teilobjekten hat folgende Nachteile:

1) Ein Teilobjekt der Basisklasse wird zwei mal mit Werten versehen:
>> a) zuerst durch den Aufruf des Default-Konstruktors der Basisklasse,
>> b) danach durch die Zuweisung beim Aufruf des Konstruktors der abgeleiteten Klasse. Diese doppelte Aktion beeinträchtigt die Ausführungszeit.
2) Die private- Attribute der Basisklasse werden durch Aufrufe der entsprechenden Zugriffsmethoden mit richtigen Anfangswerten versehen.
3) Konstante Objekte können nicht durch die Zuweisung mit Werten versehen werden.
4) Eine Klasse ohne Default-Konstruktor kann nicht als Basisklasse verwendet werden.
#### Zugriffsmethoden

Zugriffsmethoden gewährleisten den kontrollierten Zugriff auf die geschützten Attribute des Objektes.

%%(cpp)
class A {
>>private: int zet;
>>public: void setZet(int z) { _eventuelle Kontrolle
>>>zet = z;
>>}
};

main () {
>>A a1;
>>a1.zet = 5;_ Fehler
>>a1.setZet(5); _OK
}
%%
#### Basisinitialisierer

Ein Basisinitialisierer dient für den Aufruf eines Konstruktors der Basisklasse und wird in der Initialisierungsliste angegeben.

![image](/uploads/ObjProg06Vererbung/oop33.gif?width=500)
&rArr; Demo 3
&rArr; Demo 4

Eine Redefinition ist die Definition einer Methode in der abgeleiteten Klasse, wenn die Basisklasse eine Methode mit gleichem Namen hat. Durch Redefinition werden die Methoden an die neuen Fähigkeiten der Klasse angepasst.

Bei einer Redefinition darf die Signatur und der Rückgabe-Typ beider Methoden verschieden sein. Eine Überladung von Methoden findet dabei nicht statt, da die abgeleitete Klasse einen neuen Geltungsbereich besitzt.
Der Compiler sucht den Namen einer öffentlichen aufzurufenden Methode zunächst in der abgeleiteten Klasse.
Findet er diesen nicht, so geht er in der Klassenhierarchie eine Stufe höher. Dank diesem Such-Verfahren wird eine Methode der Basisklasse durch die neue redefinierte Methode verdeckt.
%%(cpp)
class A
{
>>public: void m();
};
class B : public A
{
>>public: void m(int );
};
main ()
{
>>B b1;
>>b1.A::m( );
}
%%
Es gibt zwei Möglichkeiten für die Implementierung der neuen redefinierten Methode der abgeleitete Klasse:

1) komplette Neuimplementierung,
2) Aufruf der verdeckten Methode der Basisklasse mit anschließender Ergänzung.
%%(cpp)
class A
>>{
>>>public: void m();
>>};

>>class B : public A
>>{
>>>public: void m(int )
>>>{
>>>>A::m(); &#8230; ;
>>>}
>>};
%%
&rArr; Demo 5
#### Abgeleitete Klasse mit eigenen Heapdaten


Wenn die abgeleitete Klasse selbst dynamischen Daten im Heap verwaltet, dann sind folgende Methoden selbst zu definieren:

1) einen Konstruktor (oder mehrere Konstruktoren),
2) einen Destruktor,
3) einen Kopierkonstruktor und
4) einen Zuweisungsoperator.

Ein selbstdefinierter Kopierkonstruktor muss den Kopierkonstruktor der Basisklasse explizit aufrufen. Sonst wird nur Default-Konstruktor der Basisklasse automatisch aufgerufen. ´
class B :public A
{
>>B(const B & alt) :A(alt){ &#8230; }
};

Ein selbstdefinierter Zuweisungsoperator muss den Zuweisungsoperator der Basisklasse explizit aufrufen.
class B :public A
{
>>B& B::operator=(const B & alt)
>>>> {
>>>> &#8230; ;
>>>> A::operator=(alt);
>>>> &#8230; ;
>>>> }
};
&rArr; Demo 6
&rArr; Demo 7
#### Vererbung von Zugriffsrechten
Das Zugriffsrecht des Basisklasse-Elementes in der abgeleiteten Klasse:
![image](/uploads/ObjProg06Vererbung/oop35.gif?width=500)
<span style="text-decoration:underline;">protected</span>-Attribute und Methoden sind in der eigenen und in der abgeleiteten Klassen zugreifbar, nicht aber in anderen Klassen oder außerhalb der Klasse.

&rArr; Demo 8
#### private- und protected- Vererbung

In beiden Fällen ist es notwendig, in der abgeleiteten Klasse völlig neue Schnittstelle zu definieren. Ein Objekt vom Typ der abgeleiteten Klasse ist damit kein spezielles Objekt der Basisklasse. Die Ist-Beziehung geht verloren.
class A
{
>>public: int ma();
};
class B : private A{};
main()
{
>>B b1;
>> b1.ma();_ Fehler
}
Zur Implementierung der neuen Methoden kann bereits vorhandener Code aus der Basisklasse verwendet werden (Implementierungsvererbung).
#### Wiederverwendung

Eine Klasse kann verwendet werden, um neue Objekte zu definieren.
class A{};
main(){ A a1;}

Eine Klasse kann wiederverwendet werden, um neue Klassen zu definieren:

1) Eine Klasse wird wiederverwendet, indem Objekte dieser Klasse als Attribute in anderen Klassen benutzt werden.
class A{};
class B{ A a1;};

2) Wiederverwendung durch Vererbung.
class A{}; class B :public A{};

#### Zwei Formen der Wiederverwendung
<table class="data" width="80%">
>><tr>
>>><td>
>>>><b>
>>>>>durch Attribut
>>>></b>
>>></td>
>>><td>
>>>><b>
>>>>>durch Vererbung
>>>></b>
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>class A{}; <br/>
class B{ public: A a1;}; <br/>
class B{ private: A a1;};
>>></td>
>>><td>
>>>> class A{}; <br/>
class B :public A{}; <br/>
class B :private A{};
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>Elementinitialisierer für
unlösbares Teilobjekt a1:<br/>
B::B(A a):a1(a){}
>>></td>
>>><td>
>>>> Basisinitialisierer für
namenloses Teilobjekt:<br/>
B::B(A a):A(a){}
>>></td>
>></tr>
>><tr>
>>><td>
>>>>>Objekt-Beziehung,
Hat-Beziehung,
has_a-Beziehung,
Aggregation, Komposition,
Horizontale
Wiederverwendung
>>></td>
>>><td>
>>>> Klassen-Beziehung,
Ist-Beziehung,
is_a-Beziehung,
Spezialisierung,
Vertikale
Wiederverwendung
>>></td>
>></tr>
</table>
## 6.3. Mehrfachvererbung
***
CategoryObjProg