C++ Vererbung & Polymorphie

6 Kernkonzepte
Die wichtigsten Konzepte für Vererbung und Polymorphie in C++: class Derived : public Base · virtual · override · abstract · Polymorphie · Mehrfachvererbung Vererbung und Polymorphie sind Kernkonzepte der objektorientierten Programmierung in C++. Sie ermöglichen die Wiederverwendung von Code und die Entwicklung flexibler, erweiterbarer Systeme.

Vererbung – Basisklassen erweitern

class Derived : public Base
// Basisklasse class Tier { public: std::string name; void atmen() { std::cout << "Atmet..."; } }; // Abgeleitete Klasse class Hund : public Tier { public: void bellen() { std::cout << "Wuff!"; } };

Vererbung ermöglicht es, eine neue Klasse (abgeleitete Klasse) auf Basis einer bestehenden Klasse (Basisklasse) zu definieren. Die abgeleitete Klasse erbt alle Member der Basisklasse.

Vererbungsarten

Zugriff public protected private
public Basis-Member public protected private
protected Basis-Member protected protected private
private Basis-Member
Beispiele
// Basisklasse: Fahrzeug
class Fahrzeug {
public:
int geschwindigkeit = 0;
void beschleunigen(int wert) { geschwindigkeit += wert; }
void bremsen(int wert) { geschwindigkeit -= wert; }
};
// Abgeleitete Klasse: Auto
class Auto : public Fahrzeug {
public:
std::string marke;
void hupe() { std::cout << "Hup!" << std::endl; }
void showSpeed() {
std::cout << "Geschwindigkeit: " << geschwindigkeit << std::endl;
}
};
// Verwendung
Auto meinAuto;
meinAuto.marke = "Tesla";
meinAuto.beschleunigen(50); // von Fahrzeug geerbt
meinAuto.showSpeed(); // 50
meinAuto.hupe(); // Hup!
Tipp: Verwenden Sie public-Vererbung für eine "ist-ein"-Beziehung (z.B. Auto ist ein Fahrzeug). private-Vererbung für "implementiert-durch"-Beziehungen.

virtual – Dynamische Bindung

virtual · override · final
// Basisklasse mit virtual-Methode class Tier { public: virtual void laut() { std::cout << "..."; } }; // Abgeleitete Klasse mit override class Hund : public Tier { public: void laut() override { std::cout << "Wuff!"; } };

virtual ermöglicht dynamische Bindung (späte Bindung). Die aufgerufene Methode wird zur Laufzeit anhand des tatsächlichen Objekttyps bestimmt. override markiert überschriebene Methoden.

Beispiele
class Mitarbeiter {
public:
std::string name;
virtual double gehalt() const {
return 3000.0;
}
virtual ~Mitarbeiter() = default;
};
// Abgeleitete Klasse
class Manager : public Mitarbeiter {
public:
double bonus;
double gehalt() const override {
return Mitarbeiter::gehalt() + bonus;
}
};
// Polymorphe Verwendung
Mitarbeiter* m = new Manager();
std::cout << m->gehalt(); // 3000 + bonus
delete m;
Tipp: Deklarieren Sie den Destruktor der Basisklasse als virtual, damit bei Löschung über Basiszeiger auch der Destruktor der abgeleiteten Klasse aufgerufen wird.

override & final – Kontrolle der Überschreibung

override · final
// Basisklasse class Basis { public: virtual void methode(); virtual void finalMethode() final; // Kann nicht überschrieben werden }; // Abgeleitete Klasse class Abgeleitet : public Basis { public: void methode() override; // Überschreibt Basis-Methode // void finalMethode() override; // Fehler: final kann nicht überschrieben werden };

override markiert explizit, dass eine Methode eine virtuelle Methode der Basisklasse überschreibt. final verhindert die weitere Überschreibung einer Methode oder Vererbung einer Klasse.

Beispiele
// override erzwingt korrekte Überschreibung
class Shape {
public:
virtual double area() const { return 0.0; }
virtual ~Shape() = default;
};
// Korrekte Überschreibung mit override
class Circle : public Shape {
public:
double radius;
double area() const override {
return 3.14159 * radius * radius;
}
};
// final: Klasse kann nicht vererbt werden
class FinalClass final {
// ...
};
// final: Methode kann nicht überschrieben werden
class BaseWithFinal {
public:
virtual void doSomething() final;
};
// class Derived : public BaseWithFinal {
// void doSomething() override {} // Fehler: final
// };
Tipp: Verwenden Sie override immer, wenn Sie eine virtuelle Methode überschreiben. Das hilft, Fehler zu vermeiden (z.B. falsche Signatur). final schützt vor unerwünschter Überschreibung.

Abstrakte Klassen – pure virtual

virtual ... = 0
// Abstrakte Basisklasse (Interface) class Form { public: virtual double flaeche() const = 0; // Pure virtual virtual double umfang() const = 0; virtual ~Form() = default; };

Abstrakte Klassen (mit pure virtual Methoden) können nicht instanziiert werden. Sie definieren Interfaces, die von abgeleiteten Klassen implementiert werden müssen.

Beispiele
// Abstrakte Klasse: FahrzeugInterface
class IFahrzeug {
public:
virtual void starten() = 0;
virtual void stoppen() = 0;
virtual int getSpeed() const = 0;
virtual ~IFahrzeug() = default;
};
// Implementierung: Auto
class Auto : public IFahrzeug {
private:
int speed = 0;
public:
void starten() override { speed = 10; }
void stoppen() override { speed = 0; }
int getSpeed() const override { return speed; }
};
// Verwendung
Auto meinAuto;
meinAuto.starten();
std::cout << meinAuto.getSpeed(); // 10
meinAuto.stoppen();
// IFahrzeug f; // Fehler: abstrakte Klasse
Tipp: Abstrakte Klassen mit pure virtual Methoden sind das C++-Äquivalent zu Interfaces in anderen Sprachen. Sie definieren einen Vertrag, den abgeleitete Klassen erfüllen müssen.

Polymorphie – Einheitliche Schnittstelle

Basis* · dynamische Bindung · vtable
// Polymorphe Verwendung Tier* t = new Hund(); t->laut(); // Ruft Hund::laut() auf (dynamische Bindung) delete t;

Polymorphie (Vielgestaltigkeit) bedeutet, dass ein Zeiger oder eine Referenz der Basisklasse auf Objekte abgeleiteter Klassen zeigen kann. Die tatsächliche Methode wird zur Laufzeit basierend auf dem Objekttyp bestimmt.

Beispiele
// Basisklasse mit virtueller Methode
class Zahlungsmethode {
public:
virtual void zahlen(double betrag) const = 0;
virtual ~Zahlungsmethode() = default;
};
// Konkrete Zahlungsmethoden
class Kreditkarte : public Zahlungsmethode {
public:
void zahlen(double betrag) const override {
std::cout << "Kreditkarte: " << betrag << std::endl;
}
};
class PayPal : public Zahlungsmethode {
public:
void zahlen(double betrag) const override {
std::cout << "PayPal: " << betrag << std::endl;
}
};
// Polymorphe Funktion
void bezahle(const Zahlungsmethode& methode, double betrag) {
methode.zahlen(betrag);
}
// Verwendung
Kreditkarte kk;
PayPal pp;
bezahle(kk, 99.95); // "Kreditkarte: 99.95"
bezahle(pp, 49.99); // "PayPal: 49.99"
Tipp: Polymorphie ermöglicht es, Code gegen eine abstrakte Schnittstelle zu schreiben, der mit verschiedenen konkreten Implementierungen funktioniert – das ist die Grundlage für viele Design Patterns.

Mehrfachvererbung – Von mehreren Basisklassen erben

class Derived : public Base1, public Base2
// Mehrere Basisklassen class A { public: void methodeA() {} }; class B { public: void methodeB() {} }; // Mehrfachvererbung class C : public A, public B { public: void methodeC() {} };

Mehrfachvererbung ermöglicht es einer Klasse, von mehreren Basisklassen zu erben. Sie muss in C++ explizit verwendet werden und erfordert besondere Aufmerksamkeit bei Namenskonflikten und dem Diamant-Problem.

Beispiele
// Basisklassen
class Druckbar {
public:
virtual void drucken() const { std::cout << "Druckbar"; }
};
class Serialisierbar {
public:
virtual void serialisieren(std::ostream& os) const {
os << "Serialisierbar";
}
};
// Mehrfachvererbung
class Dokument : public Druckbar, public Serialisierbar {
public:
std::string inhalt;
void drucken() const override {
std::cout << "Dokument: " << inhalt;
}
void serialisieren(std::ostream& os) const override {
os << "{\"inhalt\":\"" << inhalt << "\"}";
}
};
// Verwendung
Dokument doc;
doc.inhalt = "Hallo Welt";
doc.drucken(); // "Dokument: Hallo Welt"
doc.serialisieren(std::cout); // {"inhalt":"Hallo Welt"}
// Diamond-Problem: virtual inheritance
class Base { public: int wert; };
class Derived1 : virtual public Base {};
class Derived2 : virtual public Base {};
class Diamond : public Derived1, public Derived2 {};
// Diamond d; d.wert = 42; // Eindeutig
Tipp: Verwenden Sie Mehrfachvererbung sparsam. Oft sind Komposition oder Interfaces (abstrakte Klassen) die bessere Wahl. Bei Bedarf: virtual inheritance für das Diamant-Problem.

C++ Vererbung & Polymorphie im Überblick

: public Vererbung
public, protected, private
virtual Dynamische Bindung
Späte Bindung
override Überschreibung markieren
Seit C++11
final Keine Überschreibung
Seit C++11
= 0 Pure virtual
Abstrakte Klasse
virtual Virtuelle Vererbung
Diamond-Problem

Quick Summary

: public
Vererbung
virtual
Dynamische Bindung
override
Überschreibung
= 0
Abstrakte Klasse
Basis*
Polymorphie
,
Mehrfachvererbung
class Derived : public Base · virtual void methode() = 0; · void methode() override;