Quelle est l'idée générale d'un délégué en C ++? Quels sont-ils, comment sont-ils utilisés et à quoi servent-ils?
J'aimerais d'abord en apprendre davantage sur eux dans une «boîte noire», mais un peu d'informations sur les tripes de ces choses serait également très bien.
Ce n'est pas du C ++ à l'état pur ou le plus propre, mais je remarque que la base de code sur laquelle je travaille en a en abondance. J'espère les comprendre suffisamment pour pouvoir les utiliser et ne pas avoir à me plonger dans l'horrible horrible modèle imbriqué.
Ces deux articles de The Code Project expliquent ce que je veux dire, mais pas particulièrement succinctement:
c++
delegates
delegation
SirYakalot
la source
la source
delegate
n'est pas un nom courant dans le langage C ++. Vous devez ajouter des informations à la question pour inclure le contexte dans lequel vous l'avez lue. Notez que bien que le modèle puisse être commun, les réponses peuvent différer si vous parlez de délégué en général, ou dans le contexte de C ++ CLI ou de toute autre bibliothèque qui a une implémentation particulière de délégué .Réponses:
Vous avez un nombre incroyable de choix pour obtenir des délégués en C ++. Voici ceux qui me sont venus à l'esprit.
Option 1: foncteurs:
Un objet fonction peut être créé en implémentant
operator()
Option 2: expressions lambda ( C ++ 11 uniquement)
Option 3: pointeurs de fonction
Option 4: pointeur vers les fonctions membres (solution la plus rapide)
Voir Délégué Fast C ++ (sur The Code Project ).
Option 5: std :: fonction
(ou
boost::function
si votre bibliothèque standard ne le prend pas en charge). C'est plus lent, mais c'est le plus flexible.Option 6: liaison (en utilisant std :: bind )
Permet de définir certains paramètres à l'avance, pratique pour appeler une fonction membre par exemple.
Option 7: modèles
Acceptez n'importe quoi tant qu'il correspond à la liste d'arguments.
la source
std::bind
, et les deux font vraiment la même chose, sauf que les lambdas ne sont pas polymorphes dans le sens où ils peuvent accepter différents types d'arguments.binding
dans ma liste). Vous ne pouvez pas y parvenir avec des pointeurs de fonction.Un délégué est une classe qui encapsule un pointeur ou une référence vers une instance d'objet, une méthode membre de la classe de cet objet à appeler sur cette instance d'objet et fournit une méthode pour déclencher cet appel.
Voici un exemple:
la source
Execute()
qui déclenchera l'appel de fonction sur l'objet encapsulé par le délégué.Le besoin d'implémentations de délégués C ++ est un embarras durable pour la communauté C ++. Tous les programmeurs C ++ aimeraient les avoir, donc ils les utilisent finalement malgré les faits que:
std::function()
utilise des opérations de tas (et est hors de portée pour une programmation embarquée sérieuse).Toutes les autres implémentations font des concessions soit sur la portabilité, soit sur la conformité standard à des degrés plus ou moins élevés (veuillez vérifier en inspectant les différentes implémentations de délégués ici et sur codeproject). Je n'ai pas encore vu d'implémentation qui n'utilise pas de reinterpret_casts sauvages, des "prototypes" de classe imbriquée qui, espérons-le, produisent des pointeurs de fonction de la même taille que celle transmise par l'utilisateur, des astuces de compilateur comme first forward declare, puis typedef puis déclarez à nouveau, cette fois héritant d'une autre classe ou de techniques louches similaires. Bien que ce soit une grande réussite pour les implémenteurs qui ont construit cela, c'est toujours un triste témoignage sur la façon dont le C ++ évolue.
Il est rarement souligné que maintenant, sur 3 révisions standard C ++, les délégués n'étaient pas correctement adressés. (Ou le manque de fonctionnalités de langage permettant des implémentations de délégué simples.)
Avec la façon dont les fonctions lambda C ++ 11 sont définies par la norme (chaque lambda a un type anonyme et différent), la situation ne s'est améliorée que dans certains cas d'utilisation. Mais pour le cas d'utilisation de l'utilisation de délégués dans les API de bibliothèque (DLL), les lambdas seuls ne sont toujours pas utilisables. La technique courante ici consiste à emballer d'abord le lambda dans une fonction std ::, puis à le transmettre à travers l'API.
la source
std::function
n'alloue pas toujours dynamiquementTrès simplement, un délégué fournit des fonctionnalités sur la façon dont un pointeur de fonction DEVRAIT fonctionner. Il existe de nombreuses limitations des pointeurs de fonction en C ++. Un délégué utilise une certaine méchanceté de modèle dans les coulisses pour créer un objet de type pointeur de fonction de classe de modèle qui fonctionne comme vous le souhaitez.
c'est-à-dire - vous pouvez les configurer pour qu'ils pointent sur une fonction donnée et vous pouvez les faire circuler et les appeler quand et où vous le souhaitez.
Il y a de très bons exemples ici:
la source
Une option pour les délégués en C ++ qui n'est pas mentionnée autrement ici est de le faire en style C en utilisant une fonction ptr et un argument de contexte. C'est probablement le même schéma que beaucoup de personnes qui posent cette question essaient d'éviter. Mais, le modèle est portable, efficace et utilisable dans le code embarqué et du noyau.
la source
Windows Runtime équivalent d'un objet fonction en C ++ standard. On peut utiliser toute la fonction comme paramètre (en fait c'est un pointeur de fonction). Il est principalement utilisé en conjonction avec des événements. Le délégué représente un contrat que les gestionnaires d'événements remplissent beaucoup. Cela facilite le fonctionnement d'un pointeur de fonction.
la source