Programming lesson
C++ Vererbung und Polymorphie: Ein Tutorial mit Drachen und Kühen – Lab 07 „The Cow Strikes Back“
Lerne C++ Vererbung und Polymorphie anhand des klassischen Cowsay-Labors. Mit Drachen, Eiskühen und einem Hauch von Künstlicher Intelligenz – ideal für Studierende der Programmierung.
Einführung in die Vererbung mit C++ – Das Cowsay-Labor
Das Labor „The Cow Strikes Back“ ist ein Klassiker im C++-Unterricht. Es führt dich Schritt für Schritt in die Vererbung und Polymorphie ein – zwei der wichtigsten Konzepte der objektorientierten Programmierung. Stell dir vor, du entwickelst ein System, das verschiedene Tierarten darstellt: eine normale Kuh, einen Drachen, einen Eis-Drachen. Genau das machst du hier, nur dass die Tiere durch ASCII-Kunst sprechen. Klingt nach Spielerei? Tatsächlich steckt dahinter ein tiefes Verständnis von Klassenhierarchien, das du später in KI-Anwendungen, Spieleentwicklung oder Finanzsoftware brauchst.
„Vererbung ist wie eine Familienähnlichkeit: Kinder erben Eigenschaften ihrer Eltern, können aber eigene hinzufügen oder überschreiben.“
Was ist Vererbung in C++?
Vererbung erlaubt dir, eine neue Klasse (abgeleitete Klasse) auf Basis einer bestehenden Klasse (Basisklasse) zu definieren. Die abgeleitete Klasse übernimmt alle Attribute und Methoden der Basisklasse und kann sie erweitern oder überschreiben. In unserem Labor ist Cow die Basisklasse. Dragon erbt von Cow, und IceDragon erbt von Dragon. So entsteht eine Hierarchie:
- Cow: Name und Bild einer Kuh
- Dragon: Ein Drache, der Feuer speien kann
- IceDragon: Ein Eis-Drache, der kein Feuer speit
Das ist nicht nur Theorie. In der Praxis nutzen Frameworks wie Qt oder Unreal Engine genau solche Hierarchien. Auch in KI-Modellen wie GPT-4o oder Claude Opus 4 werden Klassenhierarchien verwendet, um verschiedene Modelle zu spezialisieren.
Das Cowsay-Labor im Detail
Dein Programm heißt cowsay und wird über die Kommandozeile gesteuert. Es gibt folgende Aufrufe:
cowsay -l: Listet verfügbare Kühe aufcowsay MESSAGE: Gibt die Nachricht mit der Standard-Kuh auscowsay -n COW MESSAGE: Nutzt eine bestimmte Kuh (z. B.dragonoderice-dragon)
Wenn du einen Drachen auswählst, wird nach der Nachricht ausgegeben, ob der Drache Feuer speien kann. Dafür musst du die Polymorphie nutzen: Die Methode canBreatheFire() wird je nach tatsächlichem Typ aufgerufen.
Die Basisklasse Cow
Die Klasse Cow speichert einen Namen und ein Bild. Sie hat einen Konstruktor, Getter und eine virtuelle Setter-Methode:
class Cow {
public:
Cow(const string& _name);
string& getName();
string& getImage();
virtual void setImage(const string& _image);
};Das Schlüsselwort virtual ist entscheidend: Es ermöglicht das Überschreiben in abgeleiteten Klassen. Ohne virtual würde immer die Methode der Basisklasse aufgerufen – egal, welcher Typ tatsächlich vorliegt.
Die abgeleitete Klasse Dragon
Dragon erbt von Cow und fügt die Methode canBreatheFire() hinzu, die immer true zurückgibt. Der Konstruktor nimmt Name und Bild entgegen:
class Dragon : public Cow {
public:
Dragon(const string& _name, const string& _image);
bool canBreatheFire();
};Beachte: Der Konstruktor von Dragon ruft den Konstruktor von Cow auf. Das ist typisch für Vererbung: Die Basisklasse wird zuerst initialisiert.
Die abgeleitete Klasse IceDragon
IceDragon erbt von Dragon und überschreibt canBreatheFire(), sodass es immer false zurückgibt:
class IceDragon : public Dragon {
public:
IceDragon(const string& _name, const string& _image);
bool canBreatheFire();
};Hier siehst du Polymorphie in Aktion: Ein Dragon*-Zeiger kann auf ein IceDragon-Objekt zeigen. Wenn du canBreatheFire() aufrufst, wird die Methode der tatsächlichen Klasse ausgeführt – dank virtual (hier nicht nötig, da die Methode nicht in Cow deklariert ist, aber das Prinzip gilt).
Die HeiferGenerator-Klasse
Die bereitgestellte Klasse HeiferGenerator erzeugt eine Liste von Cow*-Zeigern. Darunter sind auch Dragon- und IceDragon-Objekte. Die Methode getDragonPointer() prüft mit dynamic_cast, ob ein Zeiger tatsächlich auf einen Drachen zeigt:
Dragon* getDragonPointer(Cow* candidate) {
return dynamic_cast<Dragon*>(candidate);
}dynamic_cast ist ein Type-Casting-Operator, der zur Laufzeit prüft, ob die Umwandlung gültig ist. Wenn nicht, gibt er nullptr zurück. Das ist ein mächtiges Werkzeug, um Polymorphie sicher zu nutzen.
Praktische Tipps zur Implementierung
- CMakeLists.txt: Stelle sicher, dass du
set(CMAKE_CXX_STANDARD 17)setzt, um C++17 zu aktivieren. - Header-Dateien: Deklariere alle Klassen in eigenen
.h-Dateien. Trenne Interface von Implementierung. - Kommandozeilenargumente: Verwende
argcundargvinmain(). Nutzestd::stringzum Vergleichen. - Fehlerbehandlung: Wenn eine Kuh nicht gefunden wird, gib „Could not find X cow!“ aus.
Warum ist das relevant? Trends und reale Anwendungen
Vererbung und Polymorphie sind nicht nur akademisch. In der Spieleentwicklung (z. B. Unity, Unreal) werden Charaktere als Klassenhierarchien modelliert. In KI-Assistenten wie ChatGPT oder Claude gibt es Basis-Modelle und spezialisierte Varianten. Auch in Finanzsystemen werden verschiedene Kontotypen (Girokonto, Sparkonto) durch Vererbung abgebildet. Aktuell (Mai 2026) ist KI-gestützte Codegenerierung ein riesiges Thema – aber das Fundament bleibt die objektorientierte Programmierung in C++.
Häufige Fehler und wie du sie vermeidest
- Vergessen von virtual: Ohne
virtualwird die Methode der Basisklasse aufgerufen – das zerstört die Polymorphie. - Falsche Include-Guards: Verwende
#ifndef/#define/#endifin Headern. - Fehlende Implementierung: Jede deklarierte Methode muss definiert sein, sonst gibt es Linker-Fehler.
- Speicherverwaltung: Die
HeiferGeneratorgibt Zeiger zurück. Du musst den Speicher nicht freigeben (es sei denn, du nutztnew).
Zusammenfassung
Mit diesem Labor lernst du die Grundlagen der Vererbung und Polymorphie in C++. Du erstellst eine Klassenhierarchie, nutzt virtual und dynamic_cast, und arbeitest mit Kommandozeilenargumenten. Das alles in einem unterhaltsamen Kontext – sprechende Kühe und Drachen. Viel Erfolg beim Programmieren!