C++-Programmierung/ Objektorientierte Programmierung/ Vererbung

Aus Wikibooks
Zur Navigation springen Zur Suche springen


Einleitung[Bearbeiten]

Wenn von Objektorientierung gesprochen wird, fällt früher oder später auch das Stichwort Vererbung. Auf dieser Seite lernen Sie anhand eines Beispiels die Grundprinzipien der Vererbung kennen.

Die Ausgangslage[Bearbeiten]

Stellen wir uns vor, dass wir in einer Firma arbeiten und in einem Programm sämtliche Personen verwalten, die mit dieser Firma in einer Beziehung stehen. Über jede Person sind folgende Daten auf jeden Fall bekannt: Name, Adresse, Telefonnummer. Um alles zusammenzufassen, haben wir uns eine Klasse geschrieben, mit deren Hilfe wir eine einzelne Person verwalten können:

(Aus Gründen der Einfachheit benutzen wir

string

s)

Nuvola-inspired-terminal.svg
 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 
 5 class Person{
 6    public:
 7 	Person(string Name, string Adresse, string Telefon) :m_name(Name), m_adr(Adresse), m_tel(Telefon){}
 8 	string getName(){ return m_name; }
 9 	string getAdr(){ return m_adr; }
10 	string getTel(){ return m_tel; }
11 	void info(){ cout << "Name: " << m_name << " Adresse: " << m_adr << " Telefon: " << m_tel << endl; }
12 
13    private:
14 	string m_name;
15 	string m_adr;
16 	string m_tel;
17 };

Dies ist natürlich eine sehr minimale Klasse, aber schließlich geht es hier ja auch um die Vererbung.

Gemeinsam und doch getrennt[Bearbeiten]

Die obige Klasse funktioniert ja eigentlich ganz gut, nur gibt es ein kleines Problem. In unserer Firma gibt es Mitarbeiter, Zulieferer, Kunden, Chefs, ... . Diese sind zwar alle Personen, sie haben jedoch jeweils noch zusätzliche Attribute (z. B. ein Mitarbeiter hat einen Lohn, während ein Kunde eine KundenNr. hat). Jetzt könnten wir natürlich für jeden unterschiedlichen Typ eine eigene Klasse schreiben, den bereits vorhanden Code der Klasse

Person

hineinkopieren und schließlich die entsprechenden Erweiterungen vornehmen.

Dieser Ansatz hat jedoch einige Probleme:

  • Er ist unübersichtlich.
  • Es kann leicht zu Kopierfehlern kommen.
  • Soll
    Person
    
    geändert werden, so muss jede Klasse einzeln bearbeitet werden.

Zum Glück bietet uns C++ aber ein mächtiges Hilfsmittel in Form der Vererbung. Anstatt alles zu kopieren, können wir den Compiler anweisen, die Klasse

Person

als Grundlage zu verwenden. Dies wird durch ein Beispiel klarer.

Beispiel[Bearbeiten]

Nuvola-inspired-terminal.svg
 1 class Mitarbeiter : public Person {
 2    public:
 3 	Mitarbeiter(string Name, string Adresse, string Telefon, int Gehalt, int MANr):Person(Name,Adresse,Telefon),
 4             m_gehalt(Gehalt), m_nummer(MANr) {}
 5 
 6    	int getGehalt(){ return m_gehalt; }
 7 	int getNummer(){ return m_nummer; }
 8 
 9    private:
10 	int m_gehalt;
11 	int m_nummer;
12 };

Erläuterung des Beispiels[Bearbeiten]

Nun wollen wir uns der Analyse des Beispiels zuwenden, um genau zu sehen, was passiert ist.

Das wichtigste im Code steht ganz am Anfang:

class Mitarbeiter : public Person

. Damit weisen wir den Compiler an, alle Elemente aus

Person

auch in

Mitarbeiter

zu übernehmen (z.B. hat

Mitarbeiter

jetzt auch eine info-Funktion und eine Membervariable

m_name

). Eine solche Klasse nennen wir abgeleitet/Kindklasse von

Person

. Des Weiteren rufen wir im Konstruktor auch den Konstruktor von

Person

auf. Wir sparen uns also sogar diesen Code. Benutzen können wir die Klasse wie gewohnt, mit der Ausnahme, dass wir jetzt auch alle Methoden von

Person

aufrufen können:

Nuvola-inspired-terminal.svg
1 Mitarbeiter Mit("Erika Mustermann", "Heidestraße 17, Köln", "123/454", 4523, 12344209);
2 Mit.info();
3 cout << Mit.getGehalt() << endl;
4 cout << Mit.getName() << endl;
Symbol move vote.svg
Thema wird später näher erläutert…
Warum wir das Schlüsselwort
public
verwenden, wird im Kapitel „Private und geschützte Vererbung“ erklärt.

protected
[Bearbeiten]

Zum Schluss werden wir noch das Prinzip der Datenkapselung auf die Vererbung erweitern. Bis jetzt kennen wir die Schlüsselwörter

public

und

private

. Machen wir folgendes Experiment: Schreiben Sie eine neue Membermethode von

Mitarbeiter

und versuchen Sie auf

m_name

aus der

Person

-Klasse zuzugreifen. Der Compiler wird einen Fehler ausgeben. Warum?

m_name

wurde in der

Person

-Klasse als

private

deklariert, das heißt, es kann nur von Objekten dieser Klasse angesprochen werden, nicht aber von abgeleiteten Klassen wie z. B.

Mitarbeiter

. Um zu vermeiden, dass wir

m_name

als

public

deklarieren müssen, gibt es

protected

. Es verhält sich ähnlich wie

private

, mit dem Unterschied, dass auch Objekte von Kindklassen auf mit diesem Schlüsselwort versehene Member zugreifen können.