Sobes.tech
Junior

Que savez-vous du mot-clé virtual en C++?

sobes.tech IA

Réponse de l'IA

virtual en C++ est utilisé pour déclarer des fonctions virtuelles dans la classe de base. Cela permet d'implémenter le polymorphisme à l'exécution (polymorphisme en temps d'exécution).

Application :

  • Définit une fonction dans la classe de base qui peut être redéfinie (override) dans les classes dérivées.
  • Lorsqu'une fonction virtuelle est appelée via un pointeur ou une référence à la classe de base, c'est en réalité l'implémentation de la fonction dans l'objet de la classe dérivée qui est appelée (si elle a été redéfinie). Cela se produit à l'exécution via la table des fonctions virtuelles (vtable).

Points clés :

  • Seules les fonctions membres de classe peuvent être virtuelles. Les fonctions globales, membres statiques et constructeurs ne peuvent pas être virtuels.
  • Les destructeurs peuvent et doivent souvent être virtuels pour éviter les fuites de mémoire lors de la suppression d'objets de classes dérivées via un pointeur vers la classe de base.
  • Si une fonction est déclarée virtual dans la classe de base, elle reste automatiquement virtuelle dans toutes les classes dérivées, même si le mot-clé virtual n'est pas utilisé explicitement (bien qu'il soit recommandé d'utiliser virtual et override dans les classes dérivées pour plus de clarté).
  • Les fonctions virtuelles pures sont déclarées avec = 0 et rendent la classe abstraite. Une telle classe ne peut pas être instanciée directement.

Exemple :

#include <iostream>

class Base {
public:
    virtual void print() {
        std::cout << "De Base" << std::endl;
    }

    virtual ~Base() {
        std::cout << "Destructeur de Base" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() override { // Utilisation de override pour indiquer la redéfinition
        std::cout << "De Derived" << std::endl;
    }

    ~Derived() override { // Utilisation de override
        std::cout << "Destructeur de Derived" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived(); // Pointeur vers la classe de base pointant vers un objet dérivé

    ptr->print(); // Appelle Derived::print() grâce à la fonction virtuelle
    delete ptr;   // Appelle les destructeurs de Derived puis de Base grâce au destructeur virtuel

    return 0;
}

Concepts liés :

  • vtable (table des fonctions virtuelles) : Table de pointeurs vers les fonctions virtuelles de la classe. Chaque objet avec des fonctions virtuelles contient un pointeur invisible (vptr) vers la vtable de sa classe.
  • vptr (pointeur vers vtable) : Nécessaire pour déterminer la fonction à appeler en temps d'exécution.
  • = 0 (fonction virtuelle pure) : Indique que la fonction n'a pas d'implémentation dans cette classe, rendant la classe abstraite.
  • override (spécificateur de redéfinition) : Indique explicitement que la fonction dans la classe dérivée redéfinit une fonction virtuelle de la classe de base. Aide le compilateur à détecter les erreurs si la signature ne correspond pas.
  • final (spécificateur) : Interdit toute redéfinition ultérieure de la fonction virtuelle ou héritage de la classe.

En résumé : virtual est le mécanisme principal pour réaliser le polymorphisme via l'héritage et le liaison dynamique en C++.