Les différences entre les fonctions virtuelles et pures virtuelles en C++

Jinku Hu 12 octobre 2023
  1. Fonctions virtuelles et leurs caractéristiques en C++
  2. Fonctions virtuelles pures et types abstraits en C++
Les différences entre les fonctions virtuelles et pures virtuelles 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
Auteur: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

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

Article connexe - C++ Function