Fonctions virtuelles C++
Fonctions virtuelles C++
Dans ce tutoriel, nous allons découvrir la fonction virtuelle C++ et son utilisation à l'aide d'exemples.
Une fonction virtuelle est une fonction membre de la classe de base que nous nous attendons à redéfinir dans les classes dérivées.
Fondamentalement, une fonction virtuelle est utilisée dans la classe de base afin de s'assurer que la fonction est surchargée . Cela s'applique particulièrement aux cas où un pointeur de classe de base pointe vers un objet d'une classe dérivée.
Par exemple, considérez le code ci-dessous :
class Base {
public:
void print() {
// code
}
};
class Derived : public Base {
public:
void print() {
// code
}
};
Plus tard, si nous créons un pointeur de Base
tapez pour pointer vers un objet de Derived
classe et appelez le print()
fonction, elle appelle le print()
fonction du Base
classe.
En d'autres termes, la fonction membre de Base
n'est pas remplacé.
int main() {
Derived derived1;
Base* base1 = &derived1;
// calls function of Base class
base1->print();
return 0;
}
Afin d'éviter cela, nous déclarons le print()
fonction du Base
classer comme virtuel en utilisant le virtual
mot-clé.
class Base {
public:
virtual void print() {
// code
}
};
Les fonctions virtuelles font partie intégrante du polymorphisme en C++. Pour en savoir plus, consultez notre tutoriel sur le polymorphisme C++.
Exemple 1 :Fonction virtuelle C++
#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;
}
Sortie
Derived Function
Ici, nous avons déclaré le print()
fonction de Base
comme virtual
.
Ainsi, cette fonction est remplacée même lorsque nous utilisons un pointeur de Base
type qui pointe vers le Derived
objet dérivé1 .

Identifiant de remplacement C++
C++ 11 nous a donné un nouvel identifiant override
c'est très utile pour éviter les bugs lors de l'utilisation des fonctions virtuelles.
Cet identifiant spécifie les fonctions membres des classes dérivées qui remplacent la fonction membre de la classe de base.
Par exemple,
class Base {
public:
virtual void print() {
// code
}
};
class Derived : public Base {
public:
void print() override {
// code
}
};
Si nous utilisons un prototype de fonction en Derived
class et définissons cette fonction en dehors de la classe, nous utilisons alors le code suivant :
class Derived : public Base {
public:
// function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}
Utilisation du remplacement C++
Lors de l'utilisation de fonctions virtuelles, il est possible de faire des erreurs lors de la déclaration des fonctions membres des classes dérivées.
Utilisation du override
l'identifiant invite le compilateur à afficher des messages d'erreur lorsque ces erreurs sont commises.
Sinon, le programme se compilera simplement mais la fonction virtuelle ne sera pas remplacée.
Certaines de ces erreurs possibles sont :
- Fonctions avec des noms incorrects : Par exemple, si la fonction virtuelle dans la classe de base est nommée
print()
, mais nous nommons accidentellement la fonction prioritaire dans la classe dérivée commepint()
. - Fonctions avec différents types de retour : Si la fonction virtuelle est, disons, de
void
type mais la fonction dans la classe dérivée est deint
taper. - Fonctions avec différents paramètres : Si les paramètres de la fonction virtuelle et les fonctions des classes dérivées ne correspondent pas.
- Aucune fonction virtuelle n'est déclarée dans la classe de base.
Utilisation des fonctions virtuelles C++
Supposons que nous ayons une classe de base Animal
et classes dérivées Dog
et Cat
.
Supposons que chaque classe ait un membre de données nommé type . Supposons que ces variables soient initialisées via leurs constructeurs respectifs.
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") {}
... .. ...
};
Supposons maintenant que notre programme nous demande de créer deux public
fonctions pour chaque classe :
getType()
pour renvoyer la valeur de typeprint()
pour imprimer la valeur de type
Nous pourrions créer ces deux fonctions dans chaque classe séparément et les remplacer, ce qui serait long et fastidieux.
Ou nous pourrions faire getType()
virtuel dans le Animal
class, puis créez un seul print()
séparé fonction qui accepte un pointeur de Animal
type comme argument. Nous pouvons ensuite utiliser cette fonction unique pour remplacer la fonction virtuelle.
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
Cela rendra le code plus court , plus propre , et moins répétitif .
Exemple 2 :Démonstration de fonction virtuelle C++
// 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;
}
Sortie
Animal: Animal Animal: Dog Animal: Cat
Ici, nous avons utilisé la fonction virtuelle getType()
et un Animal
pointeur ani afin d'éviter de répéter le print()
fonction dans chaque classe.
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
En main()
, nous avons créé 3 Animal
des pointeurs pour créer dynamiquement des objets de Animal
, Dog
et Cat
cours.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
On appelle alors le print()
fonction en utilisant ces pointeurs :
- Quand
print(animal1)
est appelée, le pointeur pointe vers unAnimal
objet. Donc, la fonction virtuelle dansAnimal
la classe est exécutée à l'intérieur deprint()
. - Quand
print(dog1)
est appelée, le pointeur pointe vers unDog
objet. Ainsi, la fonction virtuelle est remplacée et la fonction deDog
est exécuté à l'intérieur deprint()
. - Quand
print(cat1)
est appelée, le pointeur pointe vers unCat
objet. Ainsi, la fonction virtuelle est remplacée et la fonction deCat
est exécuté à l'intérieur deprint()
.
Langue C