Pourquoi remplacer l'opérateur()?
Dans le Stimuler Les Signaux de la bibliothèque, ils sont la surcharge de l' () de l'opérateur.
Est-ce une convention en C++? Pour les rappels, etc.?
J'ai vu cela dans le code d'un co-travailleur (qui se trouve être un gros coup de pouce de ventilateur). De tout l'élan de bonté là-bas, ce qui a entraîné de la confusion pour moi.
Aucune indication quant à la raison de cette surcharge?
Vous devez vous connecter pour publier un commentaire.
L'un des objectif principal en cas de surcharge de l'opérateur() est de créer un foncteur. Un foncteur agit comme une fonction, mais il a l'avantage qu'il est dynamique, le sens qu'il peut conserver les données reflétant son état entre les appels.
Ici est un foncteur simple exemple :
Foncteurs sont fortement utilisés avec la programmation générique. De nombreux algorithmes de la STL sont écrits d'une manière très générale, de sorte que vous pouvez plug-in de votre propre fonction/foncteur dans l'algorithme. Par exemple, l'algorithme std::for_each vous permet d'appliquer une opération sur chaque élément d'une série. Il pourrait être mis en place quelque chose comme ça :
Vous voyez que cet algorithme est très générique, car il est paramétrée par une fonction. En utilisant l'opérateur(), cette fonction vous permet d'utiliser soit un foncteur ou un pointeur de fonction. Voici un exemple montrant les deux possibilités :
Concernant votre question sur l'opérateur() la surcharge, et oui c'est possible. Vous pouvez parfaitement écrire un foncteur qui a plusieurs opérateur parenthèses, aussi longtemps que vous respectez les règles de base de la surcharge de méthode (par exemple, la surcharge uniquement sur le type de retour n'est pas possible).
operator()
une fonction? Comment pourrait-il avoir un avantage pour inline-dessus de toute autre fonction? La seule façon dont il pourrait faire toute la différence est simplement une question de convention; les fonctions membres sont souvent écrites inline alors que la libre-debout les fonctions ne sont pas. C'est facile à changer si vous savez que vous allez être en utilisant la libre-debout fonction dans un contexte où l'in-lining serait précieuse.for_each
dans l'exemple ci-dessus. Si je passe une fonction libre pour le troisième paramètre, alors il serait instancierfor_each
pour le typeint(*)(int)
. Au moment de la compilation, qui ne nous dit rien sur ce qui est appelé. Il nous dit que, au moment de l'exécution, nous allons obtenir un pointeur, et que le pointeur de nous dire de quelle fonction appeler. Le compilateur ne connaît pas la fonction qui sera appelée, donc il ne peut pas inline l'appelAccumulator
défini ci-dessus, puisfor_each
est instancié pourAccumulator
, et la fonction qui est appelée dans son corps estAccumulator::operator()(int)
. Ainsi, le compilateur sait que la fonction qui va être appelée, indépendamment de la valeur réelle soit passé au moment de l'exécution. Qui lui permet d'trivialement inline l'appelIl permet à une catégorie d'agir comme une fonction. Je l'ai utilisé dans une classe de log où l'appel doit être une fonction, mais je voulais l'avantage supplémentaire de la classe.
donc quelque chose comme ceci:
se transforme en ceci:
Beaucoup ont répondu qu'il fait un foncteur, sans le dire à une grande raison pourquoi un foncteur de mieux qu'une bonne vieille fonction.
La réponse est qu'un foncteur peuvent avoir l'état. Envisager un résumé, la fonction, il faut garder en cours d'exécution totale.
Un foncteur n'est pas une fonction, de sorte que vous ne pouvez pas le surcharger.
Votre co-travailleur est correct, cependant, que la surcharge de l'opérateur() est utilisée pour créer des "foncteurs" - objets qui peuvent être appelées comme des fonctions. En combinaison avec des modèles attend de la fonction "like" arguments cela peut être très puissant, car la distinction entre un objet et une fonction devient floue.
Que d'autres affiches ont dit: foncteurs ont un avantage sur la plaine fonctions qu'ils peuvent avoir l'état. Cet état peut être utilisé sur une seule itération (par exemple pour calculer la somme de tous les éléments dans un conteneur) ou au cours de plusieurs itérations (par exemple, pour trouver tous les éléments dans plusieurs conteneurs de satisfaire à des critères particuliers).
Commencer à utiliser
std::for_each
,std::find_if
, etc. le plus souvent dans votre code et vous verrez pourquoi il est bon d'avoir la capacité de surcharge de l' () de l'opérateur. Il permet également de foncteurs et les tâches d'avoir une bonne méthode d'appel qui n'entre pas en conflit avec le nom d'autres méthodes dans les classes dérivées.Vous pouvez également regarder au-dessus de la C++ faq Matrice exemple. Il y a de bons usages pour le faire, mais cela dépend bien sûr de ce que vous essayez d'accomplir.
Les foncteurs sont fondamentalement comme des pointeurs de fonction. Ils sont généralement destinés à être copiable (comme les pointeurs de fonction) et invoquées dans la même manière que les pointeurs de fonction. Le principal avantage est que lorsque vous avez un algorithme qui fonctionne avec un basé sur un modèle foncteur, la fonction d'appel à l'opérateur() peut être insérée. Cependant, les pointeurs de fonction sont toujours valables foncteurs.
L'utilisation de l'opérateur() pour former les foncteurs en C++ est liée à programmation fonctionnelle paradigmes qui font habituellement l'utilisation d'un concept similaire: fermetures.
Une force, je peux le voir, cependant, cela peut être discuté, c'est que la signature de l'opérateur() ressemble et se comporte de la même sur tous les différents types. Si nous avions une classe Reporter, qui avait un membre de la méthode de rapport(..), et puis une autre classe de l'Écrivain, qui avait un membre de la méthode write(..), nous aurions à écrire des adaptateurs si nous souhaitons utiliser les deux classes que peut-être un modèle de composant d'un autre système. Il ne se soucient que de passer sur des chaînes ou ce que vous avez. Sans l'utilisation de l'opérateur() d'une surcharge ou d'écriture spécial de type adaptateurs, vous ne pouviez pas faire des trucs comme
parce que T a une condition qu'il n'y est une fonction membre appelée écriture qui accepte rien implicitement moulage à const char* (ou plutôt const char[]). Le Journaliste de la classe dans cet exemple n'ont qu', donc avoir T (un paramètre du modèle) étant Journaliste de ne pas compiler.
Cependant, aussi loin que je peux voir, ce serait de travailler avec différents types de
bien, il a toujours l'exige explicitement que le type T est définie par l'opérateur, de sorte que nous avons toujours une exigence sur la T. Personnellement, je ne pense pas que c'est trop bizarre avec les foncteurs comme ils sont couramment utilisés, mais je préfère voir d'autres mécanismes de ce comportement. Dans des langages tels que C# vous pouviez juste passer un délégué. Je ne suis pas trop familier avec les pointeurs de fonction en C++, mais je ne pouvais imaginer que vous pourriez atteindre le même comportement qu'il aswell.
Autres que syntatic sucre comportement je ne vois pas vraiment les points forts de la surcharge d'opérateur pour effectuer ces tâches.
Je suis sûr qu'il y a plus sciemment les gens qui ont de meilleures raisons que j'ai, mais j'ai pensé que je voudrais vous exposer mon avis, pour le reste de vous faire partager.
Un collègue de travail a souligné qu'il peut être un moyen pour cacher foncteur des objets comme des fonctions. Par exemple, ceci:
Est vraiment:
Donc, est-ce à dire ceci:
Peut être utilisé pour surcharger ce ainsi?
Autres postes ont fait un bon travail de décrire comment l'opérateur() fonctionne et pourquoi il peut être utile.
J'ai récemment été à l'aide du code qui rend très large utilisation de l'opérateur(). Un inconvénient de surcharger cet opérateur, c'est que certaines IDEs deviennent de moins en moins efficace des outils de la suite. Dans Visual Studio, vous pouvez droit-cliquez sur un appel de méthode à aller à la définition de la méthode et/ou de la déclaration. Malheureusement, VS n'est pas assez intelligent pour l'indice de l'opérateur() appelle. En particulier dans le code complexe avec substituée à l'opérateur() les définitions de tous sur la place, il peut être très difficile de comprendre ce bout de code est en cours d'exécution où. Dans plusieurs cas, j'ai trouvé que j'avais à exécuter le code et le suivi par l'intermédiaire de trouver ce qui a été fait en cours d'exécution.