Pointeurs de fonctions

Pointeurs de fonctions
4.3 (85%) 4 votes





un pointeur de fonction, с++, Programmation pour les débutants, c++c ++

Il a été observé, que les pointeurs peuvent pointer vers une variété de types d'objets dans le langage de programmation C ++. plus précisément, à tous et sur toutes sortes d'objets, Les données du programme sont.

Cependant, les mêmes objets, sous forme d'objets de données conventionnelles, sont fonctions dans le programme. De là naît un désir d'essayer de définir et d'utiliser un pointeur de fonction. Créer ce programme simple (ex1.cc):

Ici, la fonction région() tout clair: il calcule l'aire d'un cercle de rayon, qui est consacré à sa, en tant que paramètre. Mais plus tard, nous déclarons un pointeur variable à une fonction:

Au moment de cette annonce, le pointeur pfunc Il n'y a rien de plus, une autre adresse dans la représentation informatique interne (4 Byte système d'exploitation 32 bits,, 8 Byte système d'exploitation 64 bits,). Ceci est exactement le même genre de interne, qui a, disons, un pointeur vers une variable entière int *. Cependant, cet indice a un type strictement défini: un pointeur de fonction, prend un paramètre de type double, et renvoie une valeur de type double. Mais sur quels points la fonction de pointeur spécifiques, à sa définition - peu importe: la valeur de l'index n'a pas été défini.

Mais le prochain opérateur d'affectation, nous lier un pointeur de fonction à une fonction particulière région(). Absolument correct serait d'enregistrer l'attribution des adresses de pointeur de fonction: pfunc = &région. Mais le compilateur C est assez intelligent, qui référence le nom de la fonction dans l'instruction d'affectation interprète comme son adresse. Ainsi l'entrée pfunc = zone aussi tout à fait correct. De ce point, nous pouvons utiliser le pointeur pfunc pour appeler une fonction à laquelle il pointe. Pour ce faire, nous écrivons la valeur à laquelle les points de pointeur *pfunc (opération * Dans ce contexte, il est appelé déréférencer aiguille). Les parenthèses autour de la valeur déréférencé pfunc enregistrement (*pfunc)( r ) nécessaire pour des raisons de priorité des opérations en matière de divulgation. Exécution cet exemple:

un pointeur de fonction, с++, Programmation pour les débutants, c++c ++

Bien que l'utilisation des pointeurs de fonction n'a rien apporté de fondamentalement nouveau dans cet exemple,, à part quelques subtilités de syntaxe. Mais dans cet exemple, nous avons encore ne savons comment définir et utiliser des pointeurs de fonction. Et maintenant, nous pouvons passer à la question de savoir pourquoi il est nécessaire et comment nous pouvons l'utiliser.

supposant, pour un grand projet, nous préparons une série de tests, réalisée dans le processus de développement et de croissance du projet de test (la technologie de développement soi-disant test, et très productive). Le nombre de tests tour par tour dans cette situation va continuer à croître alors que nous allons de préparation du projet de base.

Dans cette situation, nous pouvons le faire (ex2.cc):

Et c'est ce que nous avons sur la performance de:

un pointeur de fonction, с++, Programmation pour les débutants, c++c ++

Dans cette liste essais[ ] – il tableau pointeurs de fonction sans paramètres et valeurs de retour sans. belle solution, est-ce pas?? Nous ne pouvons pas hésiter à ajouter de nouvelles fonctionnalités causées par essai solide, et chacun d'entre eux seront appelés dans l'ordre lors de l'exécution.

Nous pouvons aller encore plus loin: si la fonction est un pointeur vers une fonction dans une expression, vous pouvez passer un pointeur de fonction en tant que paramètre à un autre, couvrant les fonctions, et celui-ci se produiront dans votre fonction de corps pour transmettre des paramètres, ne sachant pas quelles sont les actions menées.

Pour illustrer ce qui a été dit le programme va créer la calculatrice la plus primitive, effectuer des opérations arithmétiques sur des opérandes entiers (ex3.cc):

Ici, la fonction de calcul réel effectue calculer(). Mais elle ne « savait » quoi que ce soit sur les actions en cours et opérations effectuées arithmétiques à tous: on applique au deuxième de la première de ses paramètres 6 fonctions, qu'elle a remis au 3ème paramètre pour effectuer.

Qui ne connaît pas typedef lire ici.

Cette fonction de code strtod() – une caractéristique standard de la bibliothèque C (ANSI C, standard Posix), qui extrait un nombre décimal de lignes, obtenu à partir de stdin. Dans le cadre de notre discussion est intéressante car, que:

  • un programme C ++ peut utiliser l'ensemble des appels de bibliothèque en langage C;
  • programme C ++ utilise une bibliothèque d'exécution partagée C (.alors ou .dll), et en l'absence d'une bibliothèque standard C, C ++ programme devient inutilisable.

Mais revenons à la calculatrice montré (son extrêmement simplifié en raison du fait, que nous ne traitons pas les problèmes d'entrée, son format et ne pas traiter les erreurs d'entrée utilisateur – dans les applications réelles que vous ne pouvez pas faire):

un pointeur de fonction, с++, Programmation pour les débutants, c++c ++

Observant lecteur aurait pu remarqué, que la fonction calculer() pour tout son désir et ne pouvait pas effectuer les opérations arithmétiques nécessaires, alors comment fonctionne la fonction d'action somme(), dif(), moi() et div() décrit plus tard fonctions calculer() non visible sur le code de fonction calculer().

ainsi, Nous avons examiné plusieurs occasions différentes, lorsque les fonctions C ++ sont utilisés, comme éléments de données. Ils peuvent être combinés dans des tableaux, intégré champs structures, ou transférés à d'autres fonctions en tant que paramètres. Tous ces détails et les possibilités sont réalisées au détriment des pointeurs de fonction (bien qu'ils ne peuvent pas regarder comme des pointeurs des enregistrements de syntaxe, en raison de compilateur intelligents C, qui comprend le contexte, qui doit être utilisé les adresses de fonction).

Si vous ne comprenez pas quelque chose sur le matériel ou les programmes de code – poser des questions dans les commentaires.

Nous vous proposons d'apprécier cette leçon et la leçon Pointeurs vers des objets:

Bulletin de nouvelles leçons sur la programmation:

huile

Sur huile

une expérience pratique sur le développement de logiciels 40 ans. société de logiciels internationale Global Teacher Logic. IBM Developer Works auteur permanent des publications. éditeur scientifique de l'ordinateur littérature maison d'édition "Symbole-Plus", Saint-Pétersbourg.

15 réflexions sur "Pointeurs de fonctions

  1. supplémentaire dans la virgule première cotation après la double fonction zone(deux R).

    “une adresse dans la représentation informatique interne”
    juste “une adresse”, Qu'en est-ce supplément “représentation interne”? – il ajoute quelque chose au point?

    “Nouveau dans cette PRIMER”
    faute de frappe.

    “vous pouvez passer un pointeur de fonction en tant que paramètre à un autre, couvrant les fonctions, ”
    Quelle fonction couvrant? Ce qu'il couvre?

    “Qui ne connaît pas le typedef - lire ici.”
    lien merveilleux, mais il est préférable d'écrire à ce sujet ici (il n'y a pas beaucoup).

    Le dernier exemple est terne. À mon humble avis sur les pointeurs de fonction avait à dire à ce sujet dans son ensemble (comme dans le premier exemple de l'article), Ensuite, donner un exemple d'une fonction standard qsort, qui prend un pointeur vers une fonction de comparaison. Alors complète tous quelque chose comme la fonction de recherche de la racine par bissection (ceci est un exemple très simple et fait exactement la même chose que dans qsort passer commodément une fonction en tant que paramètre).

    à savoir. l'utilisateur doit voir qu'il ya des pointeurs vers des fonctions et comprendre la syntaxe (Dans le premier exemple, vous pouvez ajouter une description typedef). puis j'ai vu, il vraiment nécessaire (une fois utilisé dans la bibliothèque standard). Eh bien, à la fin j'ai appris à écrire les mêmes fonctions, prendre un autre pointeur de fonction, comme qsort.

    Eh bien, il IMHO.

    1. > Juste « une adresse », à laquelle ce supplément est de « représentation interne »? - il ajoute quelque chose au point?

      ajoute certainement. parce que, en termes de frappe C, en particulier C ++, syntaxiquement “simplement adresses” ou “quelques adresses” il n'y a pas général (sauf que, sauf void *). Tous les pointeurs typés (et diffèrent radicalement de l'autre). Et seulement dans la représentation interne de la machine d'un pointeur vers une fonction, une méthode de classe, disons, и char * – déjà ne diffèrent pas, ils ont simplement impossibles à distinguer.

      1. > ajoute certainement. parce que, en termes de frappe C, en particulier C ++, syntaxiquement « porte simplement sur » ou « certaines adresses » n'existe pas du tout (sauf que, sauf void *). Tous les pointeurs typés … Et seulement dans la représentation interne de la machine d'un pointeur vers une fonction, une méthode de classe, disons, et char * - déjà ne diffèrent pas, ils ont simplement impossibles à distinguer.

        adresse – même adresse Afrique, peu importe ce que vous écrivez.

        #comprendre

        int main() {
        int val = 12345;
        int * intp = &val; // de type pointeur typé
        char * charp; // Un autre pointeur typé
        = crp (carboniser*)intp;

        std::cout << (int) *crp << " " << *(int *)crp << std::endl;
        }

        Ici, il est démontré que le pointeur int peut être jeté à un pointeur ombles.
        Eh bien, vous pouvez vous référer à ces données d'adresse. Dans le premier cas, déréférencé pointeur char *, de sorte que le premier octet est sélectionnée par l'adresse de val. Dans le second cas, char * est jeté à un int * déréférencement de pointeur et, donc déjà pris toutes les 4 octet.

        conclusion: 57 12345

        Dans tous les cas, avec des adresses en C, vous pouvez travailler comme vous le souhaitez. Vous pouvez prendre les données à une adresse, lire et les écrire quoi que ce soit.

        Par exemple, vous pourriez ajouter à la fin de ce programme, quelque chose comme:
        *= crp 56;

        std::cout << val << std::endl;

        autrement dit, l'adresse peut être remplacée par la variable val premier octet, travailler avec lui par un pointeur char. Et vous ne pouvez pas premier octet, car en C tout va bien avec l'arithmétique d'adresse.

    2. > Le dernier exemple est terne. À mon humble avis sur les pointeurs de fonctions a

      Mais à cette occasion: pas “J'ai eu” – et il était nécessaire de prendre et comment écrire votre texte, et ses exemples. Et ne dites pas triste “comme il aurait dû être”.

      1. Je vous écris “leurs textes” :). Par la critique calmement. Surtout quand ce, que vous avez appris ne peut pas être obtenu.

        >> Dans le cadre de notre discussion est intéressante car, que: … programme C ++ utilise une bibliothèque d'exécution partagée C (.si или .dll), et en l'absence d'une bibliothèque standard C, C ++ programme devient inutilisable.

        “Le contexte de notre discussion” – il “pointeurs de fonction” et il nous ne demandons pas ce qui se passe avec les bibliothèques partagées.

        a fortiori, que l'exactitude des informations qui pourraient être mis en doute. vous dites, ce programme C ++ en utilisant “bibliothèque partagée” langage C. terme “bibliothèque partagée” suggère, Bibliothèque qui est simultanément utilisé par de multiples processus.

        canard de, La bibliothèque comprend à l'intérieur de chaque fichier exécutable, ils ne le font pas nifiga “commun”. Comme ils ont partagé peut être utilisé pour le débogage, mais les versions vont avec option –statique toujours. Dans le cas contraire, votre programme ne fonctionnera pas sur l'ordinateur, si elle n'est pas installé la même version du compilateur, que vous avez utilisé lors du montage du programme et ne seront pas enregistrées correspondant à la façon dont votre PATH système. Ou vous pouvez, bien sûr, exécuter tous les programmes, écrit en C ++ d'un répertoire, dans lequel le lieu de racine le approprié .dll / .so, mais personne d'autre ne

      2. int Powr(int op1, int op2)
        {
        int ret = 1;
        tandis que (op2–) droite * = op1;
        retour ret;
        }

        Ce type de construction dans le degré entier. non, il est follement inefficace et peut être remplacée en utilisant les fonctions standard. Comme il est également une valeur négative tombe op2.

        PS. Si vous écrivez un article sur les pointeurs de fonction en C ++, À mon humble avis, il est nécessaire de dire au sujet std::fonctionnel. côté C ode revendiquait le titre C ++, pas son. De l'autre – funtional presque tous les points de vue est meilleure et plus pratique. Par exemple, je suis à travers elle peut transmettre lambda (Oui, et tout autre objet appelable), et par un pointeur de fonction – Je ne peux pas.

        Au lieu de cela, l'auteur a écrit des informations fausses au sujet “bibliothèque partagée”.

      3. Je suis totalement d'accord avec le commentateur suivant, leçons que vous ne reçoivent pas.

  2. int main()
    {
    //…
    retour 0; // déjà 4 Cette année, une ligne supplémentaire. Si le programme ne se termine pas anormalement, * * Il revient automatiquement à zéro le code d'erreur. à savoir. vous êtes ici pour effectuer un travail, que sans vous le compilateur exécute

    >> supposant, pour un grand projet, nous préparons une série de tests, réalisée dans le processus de développement et de croissance du projet de test (la technologie de développement soi-disant test, et très productive). … Dans cette situation, nous pouvons le faire (ex2.cc):

    Dans cette situation, en tout cas, il est impossible de le faire, vous écrivez. Tous vos efforts sont loin d'être sauvage “le développement au moyen de tests”. Посмотри на framework de test google cadre de test unitaire или boost на или на 100500 analogues.

    >>
    pour (int i = 0; je > en raison de compilateur intelligents C, qui comprend le contexte, qui doit être utilisé les adresses de fonction

    article de genre vous parlez “compilateur intelligent”. Vraiment il n'y a rien de particulièrement intelligent pour ne pas – Si le nom de la fonction n'est pas une parenthèse, stopudovo il n'est pas un appel de fonction, et un pointeur vers elle. Aucun type perverti &Je fonctionne partout, mais votre article n'a pas vu.

  3. Comment difficile tout est que j'ai avec ces pointeurs:(
    Une leçon intéressante et fait beaucoup de réflexion. Je pense qu'il est bon, mais quelques-uns des faits saillants pour moi sont restés claire. Surtout avec un tableau de pointeurs de fonction, et quelqu'un peut me répondre par typedef.
    typedef int(*fint_t)(int, int);
    OFPER fint_t[] =
    {
    summ, diff, beaucoup, DIVD, Bals, powr
    };
    Voici la vue, que la fonction du pointeur se transforme en un type de données?
    Expliquez s'il vous plaît…

    1. typedef n'introduit un nouveau type de, elle définit seulement à court synonyme pour une longue écriture “un pointeur vers une fonction ici ce type”.
      A plus déterminé tableau ces pointeurs de fonction (nommé OFPER) et il a immédiatement clairement initialisé. Etant donné que la sortie de l'initialisation de la matrice, lorsque vous essayez de le décrire, nous ne pouvons pas spécifier ([]).

  4. naturellement, que sizeof renvoie la longueur en octets, mais la condition:
    je < taille de(essais) / taille de(essais[0])
    Je ne comprends pas. expliquer pzhl.

    1. Quoi de plus simple?
      En l'occurrence le nombre d'éléments de réseau.
      Si un réseau d'éléments de 1 octet (carboniser[]) il contient 10 élément, il est 10/1 = 10.
      Si les éléments du tableau de 100 octets (structures)il contient 10 élément, il est 1000/100 = … et encore 10.

      1. Donner beaucoup de problèmes ont été sur les sujets sur ce site…merci pour les leçons!

Laisser un commentaire

Placez le code dans les balises: <pre class="lang:c ++ décodage:true ">VOTRE CODE</pré>