Les différences entre les fonctions virtuelles et pures virtuelles en C++
- Fonctions virtuelles et leurs caractéristiques en C++
- Fonctions virtuelles pures et types abstraits en C++
Cet article décrira les différences entre les fonctions virtuelles et virtuelles pures en C++.
Fonctions virtuelles et leurs caractéristiques en C++
Les fonctions virtuelles sont étroitement associées au concept de polymorphisme. En C++, nous pouvons organiser différentes classes dans une hiérarchie liée où elles peuvent partager des données membres et avoir les mêmes fonctions membres exposées que l’interface.
Généralement, les classes qui héritent d’une partie du code d’autres classes sont appelées classes dérivées, tandis que celles héritées sont les classes de base. Notez que parfois ces termes peuvent être utilisés de manière interchangeable avec les noms parent-enfant ou superclasse-sous-classe. Les fonctions qui peuvent être surchargées dans les classes dérivées sont appelées fonctions virtuelles, et elles sont déclarées avec le mot-clé virtual
. Les fonctions virtuelles ont le même nom dans la hiérarchie de classes donnée, et chaque classe dérivée peut implémenter sa propre définition de la fonction.
Si la fonction n’est pas remplacée, l’objet de classe dérivée appelle la fonction définie dans la classe de base. L’exemple de programme ci-dessous montre l’utilisation de base des fonctions virtuelles en définissant la fonction print
dans les classes Engineer
et Employee
. Ensuite, nous pouvons implémenter une fonction arbitraire Func
qui accepte la référence à Employee
et appelle la fonction print
dans le corps.
Maintenant, l’implémentation Func
peut changer plusieurs fois, mais elle appellera toujours la fonction print
correspondante en fonction de l’objet qui est passé en paramètre. On peut ajouter plusieurs classes dérivées dans la hiérarchie des classes Employee
. Chacun d’eux peut/ne peut pas implémenter la fonction print
, mais la fonction Func
acceptera leurs instances et invoquera la fonction virtuelle correcte.
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
class Employee {
public:
Employee(string fn, string ln)
: first_name(std::move(fn)), last_name(std::move(ln)) {}
virtual void print() {
cout << "name: " << first_name << "\n"
<< "last name: " << last_name << "\n";
};
protected:
string first_name, last_name;
};
class Engineer : public Employee {
public:
Engineer(string fn, string ln, string sp)
: Employee(std::move(fn), std::move(ln)), specialization(std::move(sp)) {}
void print() override {
Employee::print();
cout << "specialization: " << specialization << "\n";
}
private:
string specialization;
};
void Func(Employee &em) { em.print(); }
int main() {
Employee em1("Jim", "Jiao");
Engineer eng1("Jin", "Baker", "Aerospace Engineering");
Func(em1);
cout << "\n";
Func(eng1);
return EXIT_SUCCESS;
}
Production:
name : Jim last name : Jiao
name : Jin last name : Baker specialization
: Aerospace Engineering
Fonctions virtuelles pures et types abstraits en C++
D’autre part, nous avons le concept de fonctions virtuelles pures, qui sont déclarées similaires aux fonctions virtuelles régulières et incluent la notation = 0;
à la fin de la déclaration. Ces fonctions n’ont essentiellement pas de définition dans la classe de base, où elles sont déclarées en premier. Ainsi, ils seront très probablement définis dans les classes dérivées.
Les classes contenant des fonctions virtuelles pures sont appelées classes abstraites, et elles sont généralement utilisées pour spécifier l’interface des classes dérivées. Notez que les classes abstraites ne peuvent pas être directement instanciées.
L’extrait de code suivant implémente les classes Triangle
et Rectangle
avec la classe de base abstraite Shape
. Dans ce cas, nous avons défini la fonction virtuelle pure printArea
dans les deux classes dérivées. Parfois, une classe dérivée peut ne pas définir une fonction virtuelle pure héritée, ce qui en fait une autre classe abstraite dans la hiérarchie de classes donnée. Une classe dérivée peut hériter de plusieurs fonctions virtuelles pures. S’il ne définit même pas l’un d’entre eux, une classification abstraite est appliquée à la classe.
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Shape {
public:
virtual void printArea() = 0;
};
class Triangle : public Shape {
public:
Triangle(double b, double h) : base(b), height(h) {}
void printArea() override { cout << (base * height) / 2.0; }
private:
double base;
double height;
};
class Rectangle : public Shape {
public:
Rectangle(double i1, double i2) : edges({i1, i2}) {}
void printArea() override { cout << edges[0] * edges[1]; }
private:
vector<double> edges;
};
int main() {
Triangle t1(3, 5);
t1.printArea();
cout << "\n";
Rectangle r1(3, 5);
r1.printArea();
cout << "\n";
return EXIT_SUCCESS;
}
Production:
7.5 15
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook