Interfaces en C++ : Comment les déclarer sans se prendre la tête

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Interfaces en C++ : Guide pour ceux qui en ont assez de chercher sur Google

\n\n

Si vous avez déjà programmé en Java ou en C#, puis êtes passé au C++, vous vous êtes sûrement demandé : "Où est le mot-clé interface ?". Spoiler : il n'existe pas. En C++, les interfaces sont implémentées différemment — via des classes abstraites. Et ce n'est pas un bug, mais une fonctionnalité qui offre une flexibilité incroyable.

\n\n

Sur Stack Overflow, la question "How do you declare an interface in C++?" recueille des milliers de vues. Cela signifie que même les développeurs expérimentés s'y perdent parfois. Aujourd'hui, nous allons une fois pour toutes comprendre comment déclarer une interface en C++, pour que votre code soit propre et votre compilateur satisfait.

\n\n

Qu'est-ce qu'une interface en C++ ? (Spoiler : c'est une classe abstraite)

\n\n

En POO classique, une interface est un contrat. La classe qui implémente l'interface doit fournir une implémentation de toutes ses méthodes. En C++, ce rôle est joué par une classe abstraite — une classe contenant au moins une fonction virtuelle pure (pure virtual function).

\n\n

Retenez la règle principale :

\n
    \n
  • Interface = classe où toutes les méthodes sont virtuelles pures.
  • \n
  • Classe abstraite = classe où au moins une méthode est virtuelle pure (mais elle peut aussi avoir des méthodes normales avec implémentation).
  • \n
\n\n

Pour une interface pure, nous utilisons la première option : aucune logique, uniquement des déclarations.

\n\n

Comment déclarer une interface pure : syntaxe de base

\n\n

Voici un exemple minimal d'interface pour une figure géométrique :

\n\n
class IShape {\npublic:\n    virtual double area() const = 0;      // Fonction virtuelle pure\n    virtual double perimeter() const = 0; // Une autre\n    virtual ~IShape() {}                  // Destructeur virtuel — obligatoire !\n};
\n\n

Notez le = 0 à la fin de la déclaration. C'est le marqueur magique "virtuel pur". Une telle méthode n'a pas de corps (d'implémentation) dans la classe de base.

\n\n

Points clés :

\n
    \n
  • Préfixe I dans le nom de la classe — une convention non écrite pour les interfaces (I = Interface). Vous pouvez ne pas l'utiliser, mais cela facilite la lecture du code.
  • \n
  • Destructeur virtuel obligatoire. Si vous supprimez un objet via un pointeur vers l'interface, sans destructeur virtuel, le comportement est indéfini (autrement dit, le programme plantera).
  • \n
  • Toutes les méthodes sont public — l'interface doit être accessible depuis l'extérieur.
  • \n
\n\n

Implémentation de l'interface : des paroles aux actes

\n\n

Écrivons maintenant une classe qui implémente notre interface IShape. Que ce soit un cercle :

\n\n
class Circle : public IShape {\nprivate:\n    double radius;\npublic:\n    explicit Circle(double r) : radius(r) {}\n\n    double area() const override {\n        return 3.14159 * radius * radius;\n    }\n\n    double perimeter() const override {\n        return 2 * 3.14159 * radius;\n    }\n};
\n\n

Le mot-clé override (C++11 et versions ultérieures) n'est pas obligatoire, mais fortement recommandé. Il force le compilateur à vérifier que vous redéfinissez bien une méthode virtuelle de la classe de base. Vous avez fait une faute de frappe dans le nom ? Le compilateur dira : "Erreur ! Cette méthode n'existe pas dans l'interface".

\n\n

Polymorphisme en action

\n\n

Maintenant, la partie intéressante — nous pouvons travailler avec différentes figures via une interface unique :

\n\n
void printShapeInfo(const IShape& shape) {\n    std::cout << "Area: " << shape.area() << "\\n";\n    std::cout << "Perimeter: " << shape.perimeter() << "\\n";\n}\n\nint main() {\n    Circle c(5.0);\n    printShapeInfo(c); // Ça marche !\n    return 0;\n}
\n\n

La fonction printShapeInfo prend une référence à IShape. Peu importe quel objet est passé — un cercle, un carré ou un triangle. Tant qu'ils implémentent l'interface, tout fonctionnera. C'est cela, le polymorphisme

Blogs

Book Recommendations