Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Langue C

Maîtriser les fonctions virtuelles en C++ : Concepts, exemples et le mot-clé override

Fonctions virtuelles en C++

Ce tutoriel explique les fonctions virtuelles en C++, leur but et leur utilisation pratique illustrée avec des exemples de code.

Une fonction virtuelle est une fonction membre de classe de base que nous attendons que les classes dérivées redéfinissent. Déclarer une fonction virtuelle assure que l'implémentation la plus dérivée est invoquée, même quand on y accède via un pointeur ou une référence de classe de base.

Quand une classe de base contient un membre non virtuel, l'appel de ce membre via un pointeur de base exécutera toujours la version de base, indépendamment du type d'objet réel. Considérez ce qui suit :

class Base {
public:
    void print() {
        // implémentation de base
    }
};

class Derived : public Base {
public:
    void print() {
        // implémentation dérivée
    }
};

Dans le programme ci-dessous, un Base* pointe vers une instance Derived, pourtant print() se résout à la version de base :

int main() {
    Derived derived1;
    Base* base1 = &derived1;
    base1->print(); // appelle Base::print()
    return 0;
}

Pour obtenir un comportement polymorphe, déclarez la fonction comme virtual dans la classe de base :

class Base {
public:
    virtual void print() {
        // implémentation de base
    }
};

Les fonctions virtuelles sont centrales au polymorphisme C++. Pour une analyse plus approfondie, consultez notre guide Polymorphisme en C++.


Exemple 1 : Utilisation basique de fonction virtuelle

#include <iostream>
using namespace std;

class Base {
public:
    virtual void print() {
        cout << "Fonction de base" << endl;
    }
};

class Derived : public Base {
public:
    void print() override {
        cout << "Fonction dérivée" << endl;
    }
};

int main() {
    Derived derived1;
    Base* base1 = &derived1;
    base1->print(); // affiche Fonction dérivée
    return 0;
}

Sortie

Fonction dérivée

Puisque Base::print est virtuelle, l'appel distribue vers Derived::print même à travers un pointeur de base.

Maîtriser les fonctions virtuelles en C++ : Concepts, exemples et le mot-clé override

L'identificateur override en C++

Depuis C++11, le mot-clé override aide à prévenir les redéfinitions accidentelles en forçant le compilateur à vérifier qu'une fonction redéfinit réellement un membre virtuel de base.

Exemple :

class Base {
public:
    virtual void print() {
        // implémentation de base
    }
};

class Derived : public Base {
public:
    void print() override {
        // implémentation dérivée
    }
};

Si vous définissez la fonction de redéfinition en dehors de la classe, utilisez :

class Derived : public Base {
public:
    void print() override; // déclaration
};

void Derived::print() {
    // implémentation
}

Utilisation sécurisée de override

Sans override, une faute de frappe ou une incompatibilité de signature résulte silencieusement en une nouvelle fonction au lieu d'une redéfinition, menant à des bugs subtils. Le compilateur émettra alors une erreur, rendant le problème immédiatement visible. Pièges courants :


Utilisation pratique des fonctions virtuelles

Considérez une classe de base Animal avec des classes dérivées Dog et Cat. Chaque classe contient un membre type initialisé par son constructeur.

class Animal {
private:
    string type;
public:
    Animal() : type("Animal") {}
    virtual string getType() const {
        return type;
    }
};

class Dog : public Animal {
private:
    string type;
public:
    Dog() : type("Dog") {}
    string getType() const override {
        return type;
    }
};

class Cat : public Animal {
private:
    string type;
public:
    Cat() : type("Cat") {}
    string getType() const override {
        return type;
    }
};

Avec getType() virtuelle, un seul helper peut afficher n'importe quel animal :

void print(Animal* ani) {
    cout << "Animal : " << ani->getType() << endl;
}

Utilisation dans main() :

int main() {
    Animal* animal1 = new Animal();
    Animal* dog1 = new Dog();
    Animal* cat1 = new Cat();
    print(animal1);
    print(dog1);
    print(cat1);
    delete animal1;
    delete dog1;
    delete cat1;
    return 0;
}

Sortie

Animal : Animal
Animal : Dog
Animal : Cat

En rendant getType() virtuelle, nous évitons de dupliquer la logique print() dans chaque classe dérivée et assurons que le bon type est accédé.

Destructeur virtuel - Point crucial

Quand une classe a des fonctions virtuelles, son destructeur devrait aussi être virtuel pour assurer un nettoyage correct lors de la suppression via un pointeur de base :

class Base {
public:
    virtual ~Base() = default; // Destructeur virtuel
};

Langue C

  1. Comment passer des tableaux aux fonctions en C++ : Guide pratique
  2. Classes et objets C++ : Guide pratique de la programmation orientée objet
  3. Fonctions amies et classes amies en C++ : Maîtriser le contrôle d'accès
  4. Maîtriser les templates de classe en C++ : Guide pratique
  5. Les Fonctions en C++ Expliquées avec des Exemples de Code Pratiques
  6. Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
  7. Maîtriser les fonctions en C : Structure, déclaration et bonnes pratiques
  8. Comprendre les classes de stockage en C++ : Portée, durée de vie et utilisation
  9. Maîtriser la surcharge en C++ : Fonctions et opérateurs expliqués