Vous avez vu quelques algorithmes STL, vous êtes en mesure d'apprécier les objets fonction. Vous pouvez surcharger l'opérateur d'appel de fonction dans une classe de telle sorte que les objets de la classe puissent être utilisés à la place des pointeurs de fonction.
Ces objets sont appelés objets fonction, ou simplement foncteurs.
De nombreux algorithmes STL, tels que find_if() et la deuxième forme de l'algorithme accumulate(), nécessitent un pointeur de fonction comme l'un des paramètres. Lorsque vous utilisez ces fonctions, vous pouvez transmettre un foncteur au lieu d'un pointeur de fonction.
Ce fait, en soi, n'est pas nécessairement une raison pour sauter de joie. Bien que vous puissiez certainement écrire vos propres classes de foncteurs, le véritable attrait est que C++ fournit plusieurs classes de foncteurs prédéfinies qui effectuent les opérations de rappel les plus couramment utilisées. Cette section décrit ces classes prédéfinies et vous montre comment les utiliser.
Toutes les classes d'objets fonction prédéfinies se trouvent dans le fichier d'en-tête <functional>.
C++ fournit des modèles de classes de foncteurs pour les cinq opérateurs arithmétiques binaires: plus (plus), moins (minus), multiplie (multiplies), divise (divides) et modulo (modulus). De plus, une négation unaire est fournie (negate). Ces classes fournissent un modèle générique sur le type des opérandes et sont des wrappers pour les opérateurs réels. Ils prennent un ou deux paramètres du type de modèle, effectuent l'opération et renvoient le résultat.
L'avantage des objets fonctions arithmétiques est que vous pouvez les transmettre sous forme de fonctions de rappel aux algorithmes, ce que vous ne pouvez pas faire directement avec les opérateurs arithmétiques.
En plus des classes d'objets fonctions arithmétiques, le langage C++ fournit toutes les comparaisons standards: equal_to, not_equal_to, less, greater, less_equal et greater_equal.
Exemple:
//===============================================
void GPlus::run() {
std::plus<int> myPlus;
int res = myPlus(4, 5);
std::cout << res << std::endl;
}
//===============================================
Résultat:
//===============================================
9
//===============================================
Par exemple, l'implémentation de la fonction géométriqueMean() utilisait l'algorithme accumulate() avec une fonction de rappel pour multiplier deux entiers. Vous pouvez le réécrire pour utiliser l'objet fonction multiplie (multiplies):
Exemple:
//===============================================
void GMultiplies::run() {
std::vector<int> lVector = {10, 20, 30, 40, 50, 60};
std::cout << "geometricMean: " << geometricMean(lVector) << '\n';
}
//===============================================
double GMultiplies::geometricMean(const std::vector<int>& nums) {
double mult = std::accumulate(nums.begin(), nums.end(), 1, std::multiplies<int>());
return (pow(mult, 1.0 / nums.size()));
}
//===============================================
Résultat:
//===============================================
geometricMean: 29.938
//===============================================
L'expression multiplies<int>()
crée un nouvel objet de la classe multiplies, en l'instanciant avec le type int.
Les autres objets fonction arithmétiques se comportent de la même manière.L'objet fonction de comparaison (less) est celui utilisé par défaut par les éléments de la file d'attente prioritaire (priority_queue) et des conteneurs associatifs. Voici un exemple de file d'attente prioritaire utilisant l'opérateur de comparaison par défaut (less).
Exemple:
//===============================================
void GPriority::run() {
std::priority_queue<int> myQueue;
myQueue.push(3);
myQueue.push(4);
myQueue.push(2);
myQueue.push(1);
while (!myQueue.empty()) {
std::cout << myQueue.top() << std::endl;
myQueue.pop();
}
}
//===============================================
Résultat:
//===============================================
4
3
2
1
//===============================================
Comme vous pouvez le constater, les éléments de la file d'attente prioritaire (priority_queue) sont supprimés par ordre décroissant, selon l'opérateur de comparaison (less).
Vous pouvez modifier la comparaison en la spécifiant comme argument du modèle de comparaison.
La définition du modèle de la file d'attente prioritaire (priority_queue) ressemble à ceci:
//===============================================
template <typename T
, typename Container = vector<T>
, typename Compare = less<T> >;
//===============================================
Le paramètre de type Compare est le dernier, ce qui signifie que pour spécifier la comparaison, vous devez également spécifier le conteneur. Voici un exemple du programme ci-dessus modifié pour que la file d'attente prioritaire (priotity_queue) trie les éléments par ordre croissant en utilisant l'opérateur plus grand (greater):
Exemple:
//===============================================
void GPriority::run() {
std::priority_queue<int, std::vector<int>, std::greater<int>> myQueue;
myQueue.push(3);
myQueue.push(4);
myQueue.push(2);
myQueue.push(1);
while (!myQueue.empty()) {
std::cout << myQueue.top() << std::endl;
myQueue.pop();
}
}
//===============================================
Résultat:
//===============================================
1
2
3
4
//===============================================
Plusieurs algorithmes nécessitent des fonctions de rappel de comparaison, pour lesquels les comparateurs prédéfinis sont utiles.