Mehrfachvererbung

Ein Thema, was vielen Programmieren die Nackenhaare aufstellt und in einigen Programmiersprachen daher nicht angeboten wird: Mehrfachvererbung. Eine Klasse erbt von zwei oder mehr Basisklassen gleichberechtigt. Ein eher seltener Anwendungsfall, aber doch nicht ganz ohne Charme.

Video

 

Quellcode

 

#include <string>
#include <iostream>

class Farbe
{
  std::string name;
public:
  Farbe(std::string const &n) : name(n) { }

  std::string const &getName() const
  {
    return name;
  }
};

class Person
{
  std::string name;
public:
  Person(std::string const &n) : name(n) { }

  std::string const &getName() const
  {
    return name;
  }
};

class Felltier
{
  Farbe farbe;
public:
  Felltier(Farbe const &f) : farbe(f) { }
  
  Farbe const &getFarbe() const
  {
    return farbe;
  }
};

class Haustier
{
  Person besitzer;
public:
  Haustier(Person const &p) : besitzer(p) { }
  
  Person const &getBesitzer() const
  {
    return besitzer;
  }
};

class Katze : public Haustier, public Felltier
{
public:
  Katze(Farbe const &f, Person const &b)
    : Haustier(b), Felltier(f)
    {
    }
};

void printTier(Katze const &k)
{
  std::cout << k.getBesitzer().getName() << " hat eine " << k.getFarbe().getName() << "e Katze\n";
}

int main()
{
  Katze k(Farbe("rot"), Person("Frau Meier"));
  Katze k2(Farbe("blau"), Person("Herr Schmidt"));

  printTier(k);
  printTier(k2);
}

 Erklärung

Es gibt den – zugegebenermaßen seltenen – Fall, dass eine Klasse etwas repräsentiert, was gleichzeitig zwei Dinge sein kann. In unserem Beispiel hier ist das die Katze, die sowohl ein Felltier, als auch ein Haustier ist. Beide Vererbungsbeziehungen sind gleichberechtigt; man könnte jetzt also nicht einfach festlegen, dass eine Katze nur ein Felltier ist und die Haustier-Klasse außen vor lassen (und umgekehrt genausowenig). In diesem Fall greift die Mehrfachvererbung: die Klasse Katze erbt von beiden Basisklassen gleichzeitig und gleichberechtigt. Nach außen sichtbar ist sie also sowohl ein Felltiert, als auch ein Haustier – (mit allen entsprechenden Attributen und Schnittstellen).

Der eigentliche Spaß beginnt in Zeile 52: die Liste der Basisklassen enthält sowohl das Haustier, als auch das Felltier. Beide sind public, also auch von außen zu sehen. In Zeile 56 sehen wir noch die Initialisierung der Basisklassen: in der Reihenfolge, wie sie in der Vererbungsliste aufgeführt sind, werden die Konstruktoren mit den passenden Parametern aufgerufen. Der Rest des Quellcodes ist im Prinzip wie immer. Verwendet wird die Klasse Katze völlig normal – nur eben, dass sie problemlos als Haustier und als Felltier verwendet werden kann.

Natürlich sollen auch die Probleme der Lösung nicht verschwiegen werden: wenn zwei Basisklassen die gleiche Funktion anbieten (sowohl in Name, als auch Parameterliste gleich), dann entsteht für den Compiler eine Mehrdeutigkeit. Hier muss ihm dann explizit verraten werden, welche Version nun denn in der abgeleiteten Klasse zu verwenden ist (wie, dazu werde ich nochmal ein extra Video machen, weil das noch mehr Probleme geben kann).

Tags: