1. Pointeurs de fonction

Les fonctions sont stockées dans la zone de code de la mémoire, et elles ont aussi des adresses. Si nous avons une fonctionint test(int a), alors son adresse est le nom de la fonction. C'est exactement comme pour un tableau, où le nom du tableau est l'adresse de début du tableau.

1.1 Définition des pointeurs de fonction

data_types (*func_pointer)( data_types arg1, data_types arg2, ...,data_types argn);

Par exemple :

int (*fp)(int a); // 这里就定义了一个指向函数(这个函数参数仅仅为一个 int 类型,函数返回值是 int 类型)的指针 fp.

Exemple

int test(int a) { return a; } int main(int argc, const char * argv[]) { int (*fp)(int a); fp = test; cout<<fp(2)<<endl; return 0; }

Remarque :La fonction pointée par un pointeur de fonction doit avoir le même type de retour, le même nombre de paramètres et les mêmes types de paramètres.

1.2 L’utilisation de typedef peut simplifier la définition des pointeurs de fonction

Exemple

int test(int a) { return a; } int main(int argc, const char * argv[]) { typedef int (*fp)(int a); fp f = test; cout<<f(2)<<endl; return 0; }

1.3 Les pointeurs de fonction peuvent aussi être passés comme arguments à des fonctions

Exemple

int test(int a) { return a-1; } int test2(int (*fun)(int),int b) { int c = fun(10)+b; return c; } int main(int argc, const char * argv[]) { typedef int (*fp)(int a); fp f = test; cout<<test2(f, 1)<<endl; // Lors de l’appel de test2, l’adresse de la fonction test est passée comme argument à test2 return 0; }

En exécutant le code ci-dessus, la sortie est :

10

1.4 En utilisant des pointeurs de fonction, nous pouvons construire un tableau de pointeurs de fonction, plus précisément un tableau de pointeurs vers des fonctions

Exemple

void t1(){cout<<"test1"<<endl;} void t2(){cout<<"test2"<<endl;} void t3(){cout<<"test3"<<endl;} int main(int argc, const char * argv[]) { typedef void (*fp)(void); fp b[] = {t1,t2,t3}; // b[] est un tableau de pointeurs vers des fonctions b[0](); // L'utilisation d'opérations d'indice sur le tableau de pointeurs vers des fonctions permet des appels indirects à des fonctions return 0; }

2. Pointeurs de fonction pointant vers des fonctions membres de classe

Définition :Un pointeur de fonction membre de classe est un type de données pointeur dans le langage C++, utilisé pour stocker des informations d'accès pour une fonction membre d'une classe spécifiée qui a une liste de paramètres et un type de retour donnés.

Essentiellement, il y a deux points à noter :

  • 1. Lors de l'affectation d'un pointeur de fonction, vous devez utiliser&
  • 2. Utilisez.*(objet d'instance) ou->*(pointeur d'objet d'instance) pour appeler la fonction pointée par le pointeur de fonction membre de classe.

Regardons deux exemples ci-dessous :

A) Pointeurs de fonction membre de classe pointant vers des fonctions membres non statiques dans une classe

Pour unefonction membre non statique, prendre son adresse permet d'obtenir l'adresse réelle de la fonction en mémoire.

Pour unefonction virtuelle, son adresse est inconnue au moment de la compilation, donc pour une fonction membre virtuelle, prendre son adresse ne peut obtenir qu'une valeur d'index.

Exemple

// Pointeur de fonction pointant vers une fonction membre de classe #include <iostream> #include <cstdio> using namespace std; class A { public: A(int aa = 0):a(aa){} ~A(){} void setA(int aa = 1) { a = aa; } virtual void print() { cout << "A: " << a << endl; } virtual void printa() { cout << "A1: " << a << endl; } private: int a; }; class B:public A { public: B():A(), b(0){} B(int aa, int bb):A(aa), b(bb){} ~B(){} virtual void print() { A::print(); cout << "B: " << b << endl; } virtual void printa() { A::printa(); cout << "B: " << b << endl; } private: int b; }; int main(void) { A a; B b; void (A::*ptr)(int) = &A::setA; A* pa = &a; // Pour les fonctions non virtuelles, renvoie son adresse réelle en mémoire printf("A::set(): %p\n", &A::setA); // Pour les fonctions virtuelles, renvoie sa position de décalage dans la table des fonctions virtuelles printf("B::print(): %p\n", &A::print); printf("B::print(): %p\n", &A::printa); a.print(); a.setA(10); a.print(); a.setA(100); a.print(); // Pour un pointeur de fonction pointant vers une fonction membre de classe, le pointeur this d'un objet de classe doit être passé lors du référencement, il doit donc être appelé par une instance de classe (pa->*ptr)(1000); a.print(); (a.*ptr)(10000); a.print(); return 0; }

En exécutant le code ci-dessus, la sortie est :

A::set(): 0x8048a38
B::print(): 0x1
B::print(): 0x5
A: 0
A: 10
A: 100
A: 1000
A: 10000

B) Pointeurs de fonctions membres de classe pointant vers des fonctions membres statiques dans une classe

Exemple

#include <iostream> using namespace std; class A{ public: // p1 est un pointeur de fonction pointant vers une fonction membre non statique void (A::*p1)(void); // p2 est un pointeur de fonction pointant vers une fonction membre statique void (*p2)(void); A(){ /*Pour **les pointeurs vers des fonctions membres non statiques **et **les pointeurs vers des fonctions membres statiques **la méthode d'affectation est la même, tous deux sous la forme &ClassName::memberVariable **La différence est : **p1 ne peut être affecté qu'avec des fonctions membres non statiques **p2 ne peut être affecté qu'avec des fonctions membres statiques ** **De plus, lors de l'affectation, si vous utilisez directement &memberVariable, VS signalera « Compiler Error C2276 » **Voir : http://msdn.microsoft.com/zh-cn/library/850cstw1.aspx*/ p1 =&A::funa; // Lors de l'affectation d'un pointeur de fonction, vous devez utiliser & p2 =&A::funb; //p1 =&A::funb;//erreur //p2 =&A::funa;//erreur // p1=&funa;// erreur, Compiler Error C2276 // p2=&funb;// erreur, Compiler Error C2276 } void funa(void){ puts("A"); } static void funb(void){ puts("B"); } }; int main() { A a; // p est un pointeur de fonction pointant vers une fonction membre non statique dans A void (A::*p)(void); (a.*a.p1)(); // Affiche A // Utilisez .* (objet instance) ou ->* (pointeur d'objet instance) pour appeler la fonction pointée par le pointeur de fonction membre de classe p = a.p1; (a.*p)();// Affiche A A *b = &a; (b->*p)(); // Affiche A /*Bien que a.p2 soit lui-même une variable non statique, a.p2 est un pointeur de fonction pointant vers une fonction statique, **donc la phrase suivante est fausse !*/ // p = a.p2;//erreur void (*pp)(void); pp = &A::funb; pp(); // Affiche B return 0; }

Résumé

Les pointeurs de fonction membre de classe et les pointeurs de fonction ordinaires ne sont pas la même chose. Les premiers doivent utiliser.*et ->*opérateur pour les utiliser, tandis que les seconds peuvent utiliser*opérateur (appelé "déréférencement", ou "indirection").

Les pointeurs de fonction ordinaires stockent en fait l'adresse de début du corps de la fonction, c'est pourquoi on les appelle aussi "pointeurs de code", pour les distinguer des pointeurs de données les plus couramment utilisés en C/C++.

Les pointeurs de fonction membre de classe, cependant, ne sont pas simplement l'adresse mémoire de début de la fonction membre de classe ; ils doivent aussi résoudre le problème d'ajustement de l'adresse de l'instance de classe causé par l'héritage multiple et l'héritage virtuel de C++. Par conséquent, lors de l'appel d'un pointeur de fonction membre de classe, un objet instance de classe doit être passé.

Adresse d'origine : https://blog.csdn.net/crayondeng/article/details/16868351