C++-Programmierung/ Objektorientierte Programmierung/ Vererbung


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 strings)

#include<iostream>
#include<string>
using namespace std;

class Person{
   public:
	Person(string Name, string Adresse, string Telefon) :m_name(Name), m_adr(Adresse), m_tel(Telefon){}
	string getName(){ return m_name; }
	string getAdr(){ return m_adr; }
	string getTel(){ return m_tel; }
	void info(){ cout << "Name: " << m_name << " Adresse: " << m_adr << " Telefon: " << m_tel << endl; }

   private:
	string m_name;
	string m_adr;
	string m_tel;
};

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
class Mitarbeiter : public Person 
{
   public:
	Mitarbeiter(string Name, string Adresse, string Telefon, int Gehalt, int MANr):Person(Name,Adresse,Telefon),
            m_gehalt(Gehalt), m_nummer(MANr) {}

   	int getGehalt(){ return m_gehalt; }
	int getNummer(){ return m_nummer; }

   private:
	int m_gehalt;
	int m_nummer;
};

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:

Mitarbeiter Mit("Erika Mustermann", "Heidestraße 17, Köln", "123/454", 4523, 12344209);
Mit.info();
cout << Mit.getGehalt() << endl;
cout << Mit.getName() << endl;
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.