Virtuelle Funktionen in C++: Warum braucht ein Anfänger sie?

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Virtuelle Funktionen in C++: Warum kommt man ohne sie nicht aus?

\n\n

Stellen Sie sich vor, Sie sind Regisseur und drehen einen Film über Tiere. Sie haben ein Drehbuch: "Alle Tiere geben einen Laut von sich." Sie drehen eine Szene mit einem Hund – er bellt. Eine Szene mit einer Katze – sie miaut. Alles logisch. Und jetzt stellen Sie sich vor, Ihr Assistent (der Compiler) bringt Ihnen eine Kiste mit Spielzeugtieren und sagt: "Drehen Sie!" Sie drücken den Knopf, und das Spielzeug... schweigt. Warum? Weil Sie die virtuellen Funktionen vergessen haben.

\n\n

In der Programmierung mit C++ tritt dieses Problem ständig auf. Sie schreiben eine Klasse "Tier", darin eine Methode sound(). Dann erstellen Sie die Klassen "Hund" und "Katze", die von "Tier" erben. Und scheinbar ist alles gut, bis Sie versuchen, mit diesen Objekten über einen Zeiger auf die Basisklasse zu arbeiten. Dann stellt sich heraus, dass C++ standardmäßig die Methode der Basisklasse aufruft, nicht die überschriebene in der abgeleiteten Klasse. Virtuelle Funktionen lösen dieses Problem ein für alle Mal.

\n\n

In diesem Artikel werden wir im Detail besprechen, was virtuelle Funktionen sind, wozu sie benötigt werden, wie sie unter der Haube funktionieren und warum modernes C++ ohne sie nicht denkbar ist.

\n\n

Was ist eine virtuelle Funktion in einfachen Worten

\n\n

Eine virtuelle Funktion ist eine Methode einer Klasse, die Sie mit dem Schlüsselwort virtual kennzeichnen. Eine solche Funktion kann in abgeleiteten Klassen überschrieben werden, und beim Aufruf über einen Zeiger oder eine Referenz auf die Basisklasse wird genau die Version aus der abgeleiteten Klasse aufgerufen.

\n\n

Klingt kompliziert? Nehmen wir ein Beispiel aus dem Leben. Stellen Sie sich eine Fernbedienung für Roboter vor. Sie haben eine Basisklasse "Roboter" mit einer Methode doWork(). Es gibt einen Staubsaugerroboter und einen Lieferroboter. Wenn Sie den Knopf "Arbeiten" drücken, sollen die entsprechenden Algorithmen starten: der Staubsauger beginnt zu saugen, der Lieferroboter beginnt, ein Paket auszuliefern. Ohne virtuelle Funktionen würden Sie den Knopf drücken, und der Roboter würde einfach stillstehen (die Methode der Basisklasse würde aufgerufen).

\n\n

In C++ sind virtuelle Funktionen die Grundlage der Polymorphie. Polymorphie ermöglicht es, einheitlich mit Objekten unterschiedlicher Typen zu arbeiten, wenn sie von einem gemeinsamen Vorfahren erben.

\n\n

Das Problem ohne virtuelle Funktionen: Ein anschauliches Beispiel

\n\n

Schauen wir uns an, was passiert, wenn Sie virtual nicht verwenden.

\n\n
#include <iostream>\n#include <vector>\n\nclass Animal {\npublic:\n    void sound() {\n        std::cout << "Some generic animal sound" << std::endl;\n    }\n};\n\nclass Dog : public Animal {\npublic:\n    void sound() {\n        std::cout << "Woof! Woof!" << std::endl;\n    }\n};\n\nclass Cat : public Animal {\npublic:\n    void sound() {\n        std::cout << "Meow!" << std::endl;\n    }\n};\n\nint main() {\n    std::vector<Animal*> animals;\n    animals.push_back(new Dog());\n    animals.push_back(new Cat());\n\n    for (Animal* a : animals) {\n        a->sound(); // Was wird ausgegeben?\n    }\n\n    // Speicherbereinigung\n    for (Animal* a : animals) delete a;\n\n    return 0;\n}\n
\n\n

Führen Sie diesen Code aus. Sie werden sehen:

\n
Some generic animal sound\nSome generic animal sound\n
\n\n

Warum? Weil der Compiler auf den Typ des Zeigers schaut (Animal*), nicht auf das tatsächliche Objekt. Er ruft die Methode der Basisklasse auf. Dies nennt man frühe Bindung (early binding) – die Entscheidung, welche Methode aufgerufen wird, wird zur Compile-Zeit getroffen.

\n\n

Wir wollen aber späte Bindung (late binding) – dass die Entscheidung zur Laufzeit des Programms getroffen wird, abhängig vom Typ des Objekts. Genau das ermöglichen virtuelle Funktionen.

\n\n

Die Lösung: virtual hinzufügen

\n\n

Korrigieren wir das Beispiel, indem wir das Schlüsselwort virtual hinzufügen.

\n\n
class Animal {\npublic:\n    virtual void sound() {  // virtual hinzugefügt\n        std::cout << "Some generic animal sound" <<                

Blogs

Buchempfehlungen