Foncteurs en C++ : que sont-ils et comment simplifient-ils le code ? Guide complet

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

Que sont les foncteurs en C++ et pourquoi en a-t-on besoin ?

\n\n

Imaginez que vous écrivez du code en C++ et que vous devez passer un comportement (une fonction) à une autre fonction, par exemple pour trier ou filtrer des données. La solution classique est d'utiliser des pointeurs de fonction. Mais ils ont des inconvénients : ils ne stockent pas d'état, ils sont difficiles à intégrer (inline) et ils semblent un peu archaïques. C'est là qu'interviennent les foncteurs en C++ (également appelés objets-fonctions ou objets fonctionnels C++).

\n\n

Un foncteur est une classe ou une structure ordinaire dans laquelle l'opérateur d'appel de fonction operator() est surchargé. Grâce à cela, une instance d'une telle classe peut être utilisée comme une fonction ordinaire. Cela semble compliqué ? En réalité, c'est l'un des outils les plus élégants du C++. Sur Stack Overflow, la question "What are C++ functors and their uses?" a recueilli des milliers de vues — les développeurs veulent comprendre ce sujet pour écrire un code plus flexible et plus performant. Dans ce guide, nous allons tout détailler : de la syntaxe de base aux exemples concrets d'utilisation avec la STL.

\n\n

Syntaxe de base : comment créer votre premier foncteur

\n\n

La création d'un foncteur se résume à trois étapes :

\n
    \n
  • Déclarer une classe ou une structure.
  • \n
  • Implémenter à l'intérieur operator() avec la signature souhaitée (paramètres et type de retour).
  • \n
  • Créer un objet de cette classe et l'appeler comme une fonction.
  • \n
\n\n

Voici un exemple simple de foncteur C++ qui multiplie un nombre par deux :

\n\n
#include <iostream>\n\nclass Multiplier {\npublic:\n    // Surcharge de l'opérateur ()\n    int operator()(int x) const {\n        return x * 2;\n    }\n};\n\nint main() {\n    Multiplier mult;  // Création d'un objet-fonction\n    std::cout << mult(5) << std::endl; // Affiche : 10\n    std::cout << mult(10) << std::endl; // Affiche : 20\n    return 0;\n}
\n\n

Notez que mult(5) ressemble à un appel de fonction ordinaire, mais il s'agit en réalité d'un appel à mult.operator()(5). Le compilateur fait du sucre syntaxique, et le code devient propre et intuitif.

\n\n

Avantage principal : les foncteurs peuvent stocker un état

\n\n

Contrairement aux fonctions ordinaires ou aux expressions lambda (avant C++11), les objets fonctions C++ peuvent avoir leurs propres champs membres. Cela ouvre d'énormes possibilités. Par exemple, vous pouvez créer un foncteur qui non seulement effectue une action, mais mémorise également combien de fois il a été appelé :

\n\n
#include <iostream>\n\nclass Counter {\nprivate:\n    int count = 0;\npublic:\n    int operator()() {\n        return ++count;\n    }\n    int getCount() const { return count; }\n};\n\nint main() {\n    Counter counter;\n    std::cout << counter() << std::endl; // 1\n    std::cout << counter() << std::endl; // 2\n    std::cout << counter() << std::endl; // 3\n    // L'état est conservé entre les appels !\n    return 0;\n}
\n\n

Cet exemple de foncteur C++ avec état ne peut pas être réalisé avec une simple fonction sans utiliser de variables globales (ce qui est mauvais). Les foncteurs résolvent ce problème de manière élégante et sûre.

\n\n

Foncteurs et algorithmes STL : une combinaison parfaite

\n\n

L'utilisation la plus puissante des foncteurs est le travail avec les algorithmes de la Standard Template Library (STL). Les algorithmes comme std::sort, std::find_if, std::for_each attendent en entrée un objet appelable (callable). Vous pouvez leur passer un foncteur, et il exécutera la logique souhaitée.

\n\n

Exemple : tri avec un foncteur

\n\n

Supposons que vous ayez un vecteur de nombres et que vous souhaitiez les trier par ordre décroissant. Vous pouvez écrire votre propre foncteur de comparaison :

\n\n
#include <iostream>\n#include <vector>\n#include <algorithm>\n\nclass Descending {\npublic:\n    bool operator()(int a, int b) const {\n        return a > b; // Retourne                

Blogs

Book Recommendations