Virtuelle C++-Funktionen
Virtuelle C++-Funktionen
In diesem Tutorial lernen wir die virtuelle C++-Funktion und ihre Verwendung anhand von Beispielen kennen.
Eine virtuelle Funktion ist eine Mitgliedsfunktion in der Basisklasse, von der wir erwarten, dass sie in abgeleiteten Klassen neu definiert wird.
Grundsätzlich wird in der Basisklasse eine virtuelle Funktion verwendet, um sicherzustellen, dass die Funktion überschrieben wird . Dies gilt insbesondere für Fälle, in denen ein Zeiger der Basisklasse auf ein Objekt einer abgeleiteten Klasse zeigt.
Betrachten Sie beispielsweise den folgenden Code:
class Base {
public:
void print() {
// code
}
};
class Derived : public Base {
public:
void print() {
// code
}
};
Später, wenn wir einen Zeiger von Base
erstellen Typ, um auf ein Objekt von Derived
zu zeigen Klasse und rufen Sie print()
auf Funktion, ruft sie den print()
auf Funktion des Base
Klasse.
Mit anderen Worten, die Mitgliedsfunktion von Base
wird nicht überschrieben.
int main() {
Derived derived1;
Base* base1 = &derived1;
// calls function of Base class
base1->print();
return 0;
}
Um dies zu vermeiden, deklarieren wir den print()
Funktion des Base
Klasse als virtuell, indem Sie virtual
verwenden Schlüsselwort.
class Base {
public:
virtual void print() {
// code
}
};
Virtuelle Funktionen sind ein integraler Bestandteil des Polymorphismus in C++. Weitere Informationen finden Sie in unserem Tutorial zu C++-Polymorphismus.
Beispiel 1:Virtuelle C++-Funktion
#include <iostream>
using namespace std;
class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1;
// pointer of Base type that points to derived1
Base* base1 = &derived1;
// calls member function of Derived class
base1->print();
return 0;
}
Ausgabe
Derived Function
Hier haben wir den print()
deklariert Funktion von Base
als virtual
.
Diese Funktion wird also überschrieben, selbst wenn wir einen Zeiger von Base
verwenden Typ, der auf Derived
zeigt Objekt abgeleitet1 .
C++-Überschreibungskennung
C++ 11 hat uns einen neuen Bezeichner override
gegeben das ist sehr nützlich, um Fehler bei der Verwendung virtueller Funktionen zu vermeiden.
Dieser Bezeichner gibt die Mitgliedsfunktionen der abgeleiteten Klassen an, die die Mitgliedsfunktion der Basisklasse überschreiben.
Zum Beispiel
class Base {
public:
virtual void print() {
// code
}
};
class Derived : public Base {
public:
void print() override {
// code
}
};
Wenn wir einen Funktionsprototyp in Derived
verwenden class und definieren diese Funktion außerhalb der Klasse, dann verwenden wir den folgenden Code:
class Derived : public Base {
public:
// function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}
Verwendung von C++-Override
Bei der Verwendung virtueller Funktionen ist es möglich, beim Deklarieren der Elementfunktionen der abgeleiteten Klassen Fehler zu machen.
Verwenden Sie den override
Bezeichner fordert den Compiler auf, Fehlermeldungen anzuzeigen, wenn diese Fehler gemacht werden.
Andernfalls wird das Programm einfach kompiliert, aber die virtuelle Funktion wird nicht überschrieben.
Einige dieser möglichen Fehler sind:
- Funktionen mit falschen Namen: Zum Beispiel, wenn die virtuelle Funktion in der Basisklasse
print()
heißt , aber wir benennen die überschreibende Funktion in der abgeleiteten Klasse versehentlich alspint()
. - Funktionen mit unterschiedlichen Rückgabetypen: Wenn die virtuelle Funktion beispielsweise
void
ist type, aber die Funktion in der abgeleiteten Klasse istint
Typ. - Funktionen mit unterschiedlichen Parametern: Wenn die Parameter der virtuellen Funktion und der Funktionen in den abgeleiteten Klassen nicht übereinstimmen.
- In der Basisklasse ist keine virtuelle Funktion deklariert.
Verwendung von virtuellen C++-Funktionen
Angenommen, wir haben eine Basisklasse Animal
und abgeleitete Klassen Dog
und Cat
.
Angenommen, jede Klasse hat ein Datenelement namens type . Angenommen, diese Variablen werden durch ihre jeweiligen Konstruktoren initialisiert.
class Animal {
private:
string type;
... .. ...
public:
Animal(): type("Animal") {}
... .. ...
};
class Dog : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Dog") {}
... .. ...
};
class Cat : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Cat") {}
... .. ...
};
Nehmen wir nun an, dass unser Programm erfordert, dass wir zwei public
erstellen Funktionen für jede Klasse:
getType()
um den Wert von type zurückzugebenprint()
um den Wert von type zu drucken
Wir könnten diese beiden Funktionen in jeder Klasse separat erstellen und überschreiben, was langwierig und mühsam wäre.
Oder wir könnten getType()
machen virtuell im Animal
Klasse, erstellen Sie dann einen einzelnen, separaten print()
Funktion, die einen Zeiger von Animal
akzeptiert Typ als Argument. Wir können dann diese einzelne Funktion verwenden, um die virtuelle Funktion zu überschreiben.
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
Dadurch wird der Code kürzer , Reiniger , und weniger repetitiv .
Beispiel 2:Virtuelle C++-Funktionsdemonstration
// C++ program to demonstrate the use of virtual function
#include <iostream>
#include <string>
using namespace std;
class Animal {
private:
string type;
public:
// constructor to initialize type
Animal() : type("Animal") {}
// declare virtual function
virtual string getType() {
return type;
}
};
class Dog : public Animal {
private:
string type;
public:
// constructor to initialize type
Dog() : type("Dog") {}
string getType() override {
return type;
}
};
class Cat : public Animal {
private:
string type;
public:
// constructor to initialize type
Cat() : type("Cat") {}
string getType() override {
return type;
}
};
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
int main() {
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
print(animal1);
print(dog1);
print(cat1);
return 0;
}
Ausgabe
Animal: Animal Animal: Dog Animal: Cat
Hier haben wir die virtuelle Funktion getType()
verwendet und ein Animal
Zeiger ani um die Wiederholung des print()
zu vermeiden Funktion in jeder Klasse.
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
In main()
, haben wir 3 Animal
erstellt Zeiger zum dynamischen Erstellen von Objekten von Animal
, Dog
und Cat
Klassen.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
Wir rufen dann die print()
an Funktion mit diesen Zeigern:
- Bei
print(animal1)
aufgerufen wird, zeigt der Zeiger auf einenAnimal
Objekt. Also die virtuelle Funktion inAnimal
Klasse wird innerhalb vonprint()
ausgeführt . - Wenn
print(dog1)
aufgerufen wird, zeigt der Zeiger auf einenDog
Objekt. Die virtuelle Funktion wird also überschrieben und die Funktion vonDog
wird innerhalb vonprint()
ausgeführt . - Bei
print(cat1)
aufgerufen wird, zeigt der Zeiger auf einenCat
Objekt. Die virtuelle Funktion wird also überschrieben und die Funktion vonCat
wird innerhalb vonprint()
ausgeführt .
C Sprache
- Übergeben eines Arrays an eine Funktion in der C++-Programmierung
- C++-Klassen und -Objekte
- C++ Friend-Funktion und Friend-Klassen
- C++-Klassenvorlagen
- C++ Funktionen mit Programmbeispielen
- Verilog-Funktionen
- C - Funktionen
- Speicherklassen in C++
- C++-Überladung (Operator und Funktion)
- Polymorphismus in C++