52 votes

Fonction référence

Alors je viens de travailler avec des pointeurs de fonction et je me suis souvenu que vous pourriez faire ceci:

void Foo()
{
}

int main()
{
    void(& func)() = Foo;

    func(); //::Foo();
}

L'avantage étant que les références référence valide les objets (sauf s'ils sont mal utilisés), ou des fonctions dans ce cas.

L'inconvénient majeur étant que vous ne pouvez pas stocker un tableau de références et ne pouvez pas les utiliser pour la fonction de membre de pointeurs (au moins autant que j'en puis dire).

Ma question: est-ce quelqu'un les utiliser (c'est à dire, des références de fonction, pas de pointeurs de fonction), et si oui, dans quelles circonstances avez-vous trouvé utile/utile?

Le seul endroit où je peux les voir être utile au large de la chauve-souris est la liaison d'une référence à une certaine fonction lors de l'utilisation de compilation conditionnelle.

14voto

Robert Gould Points 29406

Je les utilisais auparavant pour ajouter de la personnalisation aux classes en les transmettant au constructeur de la même manière que le modèle de stratégie.

13voto

Je pense que votre exemple d'utilisation est assez bonne. Parce que si vous voulez utiliser un simple pointeur de fonction, et vous appliquez ensuite l'adresse de l'opérateur, vous obtiendrez l'adresse du pointeur de fonction. À l'aide d'une référence à la fonction va faire que l'on attend, en ce qu'elle renvoie un pointeur sur la fonction elle-même.

Je ne peux pas penser à de nombreux exemples. En gardant les références de fonction, comme vous le soulignez, a d'horribles conséquences. Un autre éventuellement indésirables conséquence est que, si tenus en tant que membre, vos objets seront incessibles si vous n'écrivez pas votre propre opérateur= et de s'abstenir d'essayer de ré-attribuer la fonction de référence.

Je pense que la plupart des utilisations de la fonction de références implicites, à l'instar de la plupart des utilisations du tableau des références bien que beaucoup plus, lorsque vous accepter des arguments par référence:

template<typename T>
void do_something(T const& t) { ... }

Tout en acceptant les tableaux par référence a l'avantage de ne pas perdre leurs informations de taille, l'acceptation de fonctions par référence explicitement, ne semble pas être un avantage (au moins autant que je peux voir). Je suppose que l'existence de références de fonction est largement justifié par la vision idéaliste d'une référence comme un aliasde nom d'un objet ou d'une fonction, en collaboration avec le fait qu'il permet le passage de fonctions à ces modèles qui acceptent leur argument par référence.

Je serais probablement éviter de les utiliser si je n'aurais pas besoin d'eux, inévitablement. Constante des pointeurs de fonction également de la non-reassignable callables, et sera probablement éviter les confusions lorsque d'autres programmeurs, qui, éventuellement, ne sont pas très familier avec cette langue de niches, de lire votre code. Vaut la peine de noter que Vandervoorde & Josuttis vous conseillons également de les éviter pour réduire les risques de confusion (dans leur livre " C++ Templates - Le Guide Complet).

11voto

LB-- Points 409

Les références de fonction, contrairement aux pointeurs de fonction, rendent plus difficile leur création à partir d'une source non valide. Ceci est utile si vous créez une enveloppe autour d'une bibliothèque C - le code C ++ peut prendre une fonction de rappel par référence et transmettre le pointeur à la bibliothèque C si le lbrary exige que le pointeur transmis ne soit pas NULL.

C'est également un moyen pratique d'aliaser une fonction, notamment en C ++ 11 avec le nouveau mot clé auto:

 #include <iostream>
#include <typeinfo>

void f(int i, char c)
{
    std::cout << i << ' ' << c << std::endl;
}

int main()
{
    std::cout << typeid(f).name() << std::endl; //FvicE
    f(0, '1');

    void (*pf)(int, char) (&f); //ugly
    std::cout << typeid(pf).name() << std::endl; //PFvicE
    (*pf)(2, '3');
    pf(4, '5'); //works, but I don't recommend it

    void (&rf)(int, char) (f); //still ugly
    std::cout << typeid(rf).name() << std::endl; //FvicE
    rf(6, '7');

    auto &af (f); //pretty, but only works in C++11
    std::cout << typeid(af).name() << std::endl; //FvicE, same as above
    af(8, '9');
}
 

3voto

Ichthyo Points 1760

en plus de l'utiliser comme stratégie (comme l'a souligné Robert Gould), je freqently les utiliser au point d'entrée (modèle) métaprogrammation. Une fonction de référence peut facilement être repris par un paramètre de modèle; à partir de ce point, il peut être passé à travers plusieurs couches de (métaprogrammation) modèles. Bien sûr, cela vaut pour un pointeur de fonction en tant que bien, mais la référence est un alias et donc communique l'intention plus clairement.

Pour donner un exemple: lors de la rédaction d'un générique de commande système de répartition d'une application, un grand nombre de différentes opérations doivent être, a annoncé que les commandes. On peut utiliser un simple "générateur de fonction" en tant que front-end pour le code client. En coulisses, ce générateur de fonction ramasse la véritable signature de fonction en tant que paramètre du modèle, dérive (par modèle de métaprogrammation) le paramètre effectif et le type de retour de valeurs et, éventuellement, choisit la spécialisation de stocker un "memento" et "annuler foncteur". Ces foncteurs peuvent être stockées soit en tant que pointeurs de fonction en interne, ou à l'aide de boost ou de tr1 ou C++11 de la fonction des objets. De cette façon, il est possible de construire un type de coffre-fort invocation de commande et "annuler" du système.

1voto

Ates Goral Points 47670

Je les ai utilisées dans un système de plug-in où les DLL de plug-in pourraient être chargées / déchargées au moment de l'exécution. Je rechercherais des symboles connus dans chaque DLL et les jetterais pour des pointeurs de fonction.

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