104 votes

Quel est le point de pointeurs de fonction?

J'ai du mal à voir l'utilité des pointeurs de fonction. J'imagine que ça peut être utile dans certains cas (ils existent, après tout), mais je ne peux pas penser à un cas où il est mieux ou inévitable d'utiliser un pointeur de fonction.

Pourriez-vous donner quelques exemple de bonne utilisation de pointeurs de fonction (en C ou C++)?

114voto

sbi Points 100828

La plupart des exemples se résument à des rappels: Vous appelez une fonction f() passant l'adresse d'une autre fonction g(), et f() des appels g() pour certains tâche spécifique. Si vous passez f() l'adresse de l' h() au lieu de cela, alors f() ne h() à la place.

En gros, c'est un moyen de paramétrer une fonction: une partie de son comportement n'est pas codée en dur dans f(), mais dans la fonction de rappel. Les appelants peuvent faire f() se comportent différemment en passant par les différentes fonctions de rappel. Un classique est - qsort() de la bibliothèque C standard qui prend son critère de tri comme un pointeur vers une fonction de comparaison.

En C++, cela se fait souvent à l'aide de la fonction des objets (aussi appelé foncteurs). Ce sont des objets que la surcharge de l'opérateur d'appel de fonction, de sorte que vous pouvez les appeler comme si elles étaient une fonction. Exemple:

class functor {
  public:
     void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
};

functor f;
f(42);

L'idée derrière cela est que, contrairement à un pointeur de fonction, un objet de fonction peut porter non seulement un algorithme, mais également des données:

class functor {
  public:
     functor(const std::string& prompt) : prompt_(prompt) {}
     void operator()(int i) {std::cout << prompt_ << i << '\n';}
  private:
     std::string prompt_;
};

functor f("the answer is: ");
f(42);

Un autre avantage est qu'il est parfois plus facile de l'inclure des appels à la fonction des objets que des appels par le biais de pointeurs de fonction. C'est une des raisons pourquoi le tri en C++ est parfois plus rapide que le tri en C.

43voto

Mawg Points 7387

Eh bien, je l'utilise généralement (professionnellement) à sauter tables (voir aussi ce StackOverflow question).

Sauter tables sont souvent (mais pas exclusivement) utilisé dans des machines à états finis pour les rendre pilotés par les données. Au lieu de imbriquée switch/case

  switch (state)
     case A:
       switch (event):
         case e1: ....
         case e2: ....
     case B:
       switch (event):
         case e3: ....
         case e1: ....

vous pouvez faire un tableau 2d ou des pointeurs de fonction et il suffit d'appeler handleEvent[state][event]

25voto

Andrey Points 36869

Exemples:

  1. Un tri personnalisé/recherches
  2. Différentes les modèles (comme la Stratégie, Observateur)
  3. Rappels

13voto

Carl Smotricz Points 36400

Le "classique" exemple pour l'utilité des pointeurs de fonction est la bibliothèque C qsort() de la fonction, qui met en œuvre un Tri Rapide. Afin d'être universelle pour toute et toutes les structures de données de l'utilisateur peuvent venir avec, on prend un couple de pointeurs void à triable de données et un pointeur vers une fonction qui sait comment comparer deux éléments de ces structures de données. Cela nous permet de créer notre fonction de choix pour le travail, et en fait même permet de choisir la fonction de comparaison au moment de l'exécution, par exemple pour le tri croissant ou décroissant.

5voto

msemack Points 3116

J'ai utilisé des pointeurs de fonction récemment de créer une couche d'abstraction.

J'ai un programme écrit en pur C qui s'exécute sur les systèmes embarqués. Il prend en charge matérielles multiples variantes. En fonction du matériel, je suis en cours d'exécution, il doit appeler les différentes versions de certaines fonctions.

Pendant la phase d'initialisation, le programme des chiffres de ce matériel, il est en cours d'exécution sur et remplit les pointeurs de fonction. L'ensemble de la hausse du niveau des routines dans le programme à appeler les fonctions référencées par des pointeurs. Je peux ajouter la prise en charge de nouveau matériel variantes sans toucher au plus haut niveau de routines.

J'ai utilisé le switch/case instructions pour choisir la bonne fonction des versions, mais cela est devenu impossible que le programme s'est étendu à l'appui de plus en plus de matériel variantes. J'ai dû ajouter de cas relevés dans tous les sens.

J'ai aussi essayé intermédiaire de la fonction de couches de comprendre la fonction à utiliser, mais ils n'ont pas beaucoup d'aide. J'ai toujours eu à mettre à jour les cas relevés dans plusieurs endroits à chaque fois que nous avons ajouté une nouvelle variante. Avec les pointeurs de fonction, je n'ai qu'à changer la fonction d'initialisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X