C++ virtuele functies
C++ virtuele functies
In deze zelfstudie leren we over de virtuele C++-functie en het gebruik ervan met behulp van voorbeelden.
Een virtuele functie is een lidfunctie in de basisklasse die we verwachten te herdefiniëren in afgeleide klassen.
In de basisklasse wordt in principe een virtuele functie gebruikt om ervoor te zorgen dat de functie overschreven wordt. . Dit is vooral van toepassing op gevallen waarin een pointer van de basisklasse naar een object van een afgeleide klasse wijst.
Beschouw bijvoorbeeld de onderstaande code:
class Base {
public:
void print() {
// code
}
};
class Derived : public Base {
public:
void print() {
// code
}
};
Later, als we een pointer van Base
. maken type om te verwijzen naar een object van Derived
klas en bel de print()
functie, roept het de print()
functie van de Base
klasse.
Met andere woorden, de ledenfunctie van Base
wordt niet overschreven.
int main() {
Derived derived1;
Base* base1 = &derived1;
// calls function of Base class
base1->print();
return 0;
}
Om dit te voorkomen, declareren we de print()
functie van de Base
class als virtueel met behulp van de virtual
zoekwoord.
class Base {
public:
virtual void print() {
// code
}
};
Virtuele functies zijn een integraal onderdeel van polymorfisme in C++. Bekijk onze tutorial over C++ polymorfisme voor meer informatie.
Voorbeeld 1:virtuele C++-functie
#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;
}
Uitvoer
Derived Function
Hier hebben we de print()
. gedeclareerd functie van Base
als virtual
.
Deze functie wordt dus overschreven, zelfs als we een aanwijzer van Base
. gebruiken type dat verwijst naar de Derived
object afgeleid1 .
C++ override Identifier
C++ 11 heeft ons een nieuwe identifier gegeven override
dat is erg handig om bugs te voorkomen tijdens het gebruik van virtuele functies.
Deze identifier specificeert de lidfuncties van de afgeleide klassen die de lidfunctie van de basisklasse overschrijven.
Bijvoorbeeld,
class Base {
public:
virtual void print() {
// code
}
};
class Derived : public Base {
public:
void print() override {
// code
}
};
Als we een functie-prototype gebruiken in Derived
class en definieer die functie buiten de klasse, dan gebruiken we de volgende code:
class Derived : public Base {
public:
// function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}
Gebruik van C++ override
Bij het gebruik van virtuele functies is het mogelijk om fouten te maken bij het declareren van de lidfuncties van de afgeleide klassen.
De override
. gebruiken identifier vraagt de compiler om foutmeldingen weer te geven wanneer deze fouten worden gemaakt.
Anders zal het programma gewoon compileren, maar de virtuele functie wordt niet overschreven.
Enkele van deze mogelijke fouten zijn:
- Functies met onjuiste namen: Als de virtuele functie in de basisklasse bijvoorbeeld
print()
. heet , maar we noemen per ongeluk de overschrijvende functie in de afgeleide klasse alspint()
. - Functies met verschillende retourtypes: Als de virtuele functie bijvoorbeeld van
void
. is type maar de functie in de afgeleide klasse is vanint
typ. - Functies met verschillende parameters: Als de parameters van de virtuele functie en de functies in de afgeleide klassen niet overeenkomen.
- Er is geen virtuele functie gedeclareerd in de basisklasse.
Gebruik van virtuele C++-functies
Stel we hebben een basisklasse Animal
en afgeleide klassen Dog
en Cat
.
Stel dat elke klasse een gegevenslid heeft met de naam type . Stel dat deze variabelen worden geïnitialiseerd via hun respectievelijke constructors.
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") {}
... .. ...
};
Laten we nu aannemen dat ons programma vereist dat we twee public
functies voor elke klasse:
getType()
om de waarde van type te retournerenprint()
om de waarde van type af te drukken
We zouden beide functies in elke klasse afzonderlijk kunnen maken en ze kunnen negeren, wat lang en vervelend zal zijn.
Of we kunnen getType()
. maken virtueel in de Animal
class en maak vervolgens een enkele, aparte print()
functie die een pointer van Animal
. accepteert typ als argument. We kunnen dan deze enkele functie gebruiken om de virtuele functie te overschrijven.
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
Dit maakt de code korter , schonere , en minder repetitief .
Voorbeeld 2:C++ virtuele functiedemonstratie
// 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;
}
Uitvoer
Animal: Animal Animal: Dog Animal: Cat
Hier hebben we de virtuele functie getType()
. gebruikt en een Animal
pointer ani om herhaling van de print()
. te voorkomen functie in elke klas.
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
In main()
, we hebben 3 Animal
. gemaakt pointers om dynamisch objecten van Animal
. te maken , Dog
en Cat
lessen.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
We noemen dan de print()
functie met behulp van deze aanwijzingen:
- Wanneer
print(animal1)
wordt aangeroepen, wijst de aanwijzer naar eenAnimal
object. Dus de virtuele functie inAnimal
class wordt uitgevoerd binnenprint()
. - Wanneer
print(dog1)
wordt aangeroepen, wijst de aanwijzer naar eenDog
object. Dus de virtuele functie wordt overschreven en de functie vanDog
wordt uitgevoerd binnenprint()
. - Wanneer
print(cat1)
wordt aangeroepen, wijst de aanwijzer naar eenCat
object. Dus de virtuele functie wordt overschreven en de functie vanCat
wordt uitgevoerd binnenprint()
.
C Taal
- Array doorgeven aan een functie in C++-programmering
- C++ klassen en objecten
- C++ vriend Functie en vriend Klassen
- C++-klassesjablonen
- C++-functies met programmavoorbeelden
- Verilog-functies
- C - Functies
- Opslagklassen in C++
- C++ overbelasting (operator en functie)
- Polymorfisme in C++
- Gegevensabstractie in C++