Une fonction de rappel est une fonction, qui est un argument, pas un paramètre, dans une autre fonction. L'autre fonction peut être appelée la fonction principale. Deux fonctions sont donc impliquées : la fonction principale et la fonction de rappel elle-même. Dans la liste des paramètres de la fonction principale, la déclaration de la fonction de rappel sans sa définition est présente, tout comme les déclarations d'objet sans affectation sont présentes. La fonction principale est appelée avec des arguments (dans main()). L'un des arguments de l'appel de fonction principale est la définition effective de la fonction de rappel. En C++, cet argument est une référence à la définition de la fonction de rappel ; ce n'est pas la vraie définition. La fonction de rappel elle-même est en fait appelée dans la définition de la fonction principale.
La fonction de rappel de base en C++ ne garantit pas un comportement asynchrone dans un programme. Le comportement asynchrone est le véritable avantage du schéma de fonction de rappel. Dans le schéma de fonction de rappel asynchrone, le résultat de la fonction principale doit être obtenu pour le programme avant que le résultat de la fonction de rappel ne soit obtenu. Il est possible de le faire en C++ ; cependant, C++ a une bibliothèque appelée future pour garantir le comportement du schéma de fonction de rappel asynchrone.
Cet article explique le schéma de base de la fonction de rappel. C'est en grande partie avec du C pur++. En ce qui concerne le rappel, le comportement de base de la future bibliothèque est également expliqué. Des connaissances de base en C++ et ses pointeurs sont nécessaires à la compréhension de cet article.
Contenu de l'article
- Schéma de fonction de rappel de base
- Comportement synchrone avec fonction de rappel
- Comportement asynchrone avec fonction de rappel
- Utilisation de base de la future bibliothèque
- Conclusion
Schéma de fonction de rappel de base
Un schéma de fonction de rappel a besoin d'une fonction principale et de la fonction de rappel elle-même. La déclaration de la fonction de rappel fait partie de la liste des paramètres de la fonction principale. La définition de la fonction de rappel est indiquée dans l'appel de fonction de la fonction principale. La fonction de rappel est en fait appelée dans la définition de la fonction principale. Le programme suivant illustre cela :
#inclureen utilisant l'espace de noms std ;
int principalFn(char ch[], int (*ptr)(int))
entier id1 = 1;
entier id2 = 2;
int idr = (*ptr)(id2);
cout<<"principal function: "<
int cb(int iden)
cout<<"callback function"<<'\n';
retour iden;
int main()
entier (*ptr)(int) = &cb;
char cha[] = "et";
principalFn(cha, cb);
renvoie 0 ;
La sortie est :
fonction de rappelfonction principale : 1 et 2
La fonction principale est identifiée par principalFn(). La fonction de rappel est identifiée par cb(). La fonction de rappel est définie en dehors de la fonction principale mais en réalité appelée dans la fonction principale.
Notez la déclaration de la fonction de rappel en paramètre dans la liste des paramètres de la déclaration de la fonction principale. La déclaration de la fonction de rappel est "int (*ptr)(int)". Notez l'expression de la fonction de rappel, comme un appel de fonction, dans la définition de la fonction principale ; tout argument pour l'appel de la fonction de rappel y est passé. L'instruction pour cet appel de fonction est :
int idr = (*ptr)(id2);Où id2 est un argument. ptr fait partie du paramètre, un pointeur, qui sera lié à la référence de la fonction de rappel dans la fonction main().
Notez l'expression :
entier (*ptr)(int) = &cb;Dans la fonction main(), qui lie la déclaration (sans définition) de la fonction de rappel au nom de la définition de la même fonction de rappel.
La fonction principale est appelée, dans la fonction main(), comme :
principalFn(cha, cb);Où cha est une chaîne et cb est le nom de la fonction de rappel sans aucun de ses arguments.
Comportement synchrone de la fonction de rappel
Considérez le programme suivant :
#inclureen utilisant l'espace de noms std ;
void principalFn(void (*ptr)())
cout<<"principal function"<<'\n';
(*ptr)();
annuler cb()
cout<<"callback function"<<'\n';
vide fn()
cout<<"seen"<<'\n';
int main()
vide (*ptr)() = &cb;
principalFn(cb);
fn();
renvoie 0 ;
La sortie est :
fonction principalefonction de rappel
vu
Il y a une nouvelle fonction ici. Tout ce que la nouvelle fonction fait, c'est d'afficher la sortie, "vu". Dans la fonction main(), la fonction principale est appelée, puis la nouvelle fonction, fn() est appelée. La sortie montre que le code de la fonction principale a été exécuté, puis celui de la fonction de rappel a été exécuté, et enfin celui de la fonction fn() a été exécuté. Il s'agit d'un comportement synchrone (à thread unique).
S'il s'agissait d'un comportement asynchrone, lorsque trois segments de code sont appelés dans l'ordre, le premier segment de code peut être exécuté, suivi à la place de l'exécution du troisième segment de code, avant que le deuxième segment de code ne soit exécuté.
Eh bien, la fonction fn() peut être appelée à partir de la définition de la fonction principale, au lieu de la fonction main(), comme suit :
#inclureen utilisant l'espace de noms std ;
vide fn()
cout<<"seen"<<'\n';
void principalFn(void (*ptr)())
cout<<"principal function"<<'\n';
fn();
(*ptr)();
annuler cb()
cout<<"callback function"<<'\n';
int main()
vide (*ptr)() = &cb;
principalFn(cb);
renvoie 0 ;
La sortie est :
fonction principalevu
fonction de rappel
Ceci est une imitation du comportement asynchrone. Ce n'est pas un comportement asynchrone. C'est toujours un comportement synchrone.
De plus, l'ordre d'exécution du segment de code de la fonction principale et du segment de code de la fonction de rappel peut être interverti dans la définition de la fonction principale. Le programme suivant illustre cela :
#inclureen utilisant l'espace de noms std ;
void principalFn(void (*ptr)())
(*ptr)();
cout<<"principal function"<<'\n';
annuler cb()
cout<<"callback function"<<'\n';
vide fn()
cout<<"seen"<<'\n';
int main()
vide (*ptr)() = &cb;
principalFn(cb);
fn();
renvoie 0 ;
La sortie est maintenant,
fonction de rappelfonction principale
vu
C'est aussi une imitation du comportement asynchrone. Ce n'est pas un comportement asynchrone. C'est toujours un comportement synchrone. Un véritable comportement asynchrone peut être obtenu comme expliqué dans la section suivante ou avec la bibliothèque, future.
Comportement asynchrone avec fonction de rappel
Le pseudo-code du schéma de fonction de rappel asynchrone de base est :
sortie de type ;tapez cb (type sortie)
//déclarations
tapez principalFn(tapez entrée, tapez cb(tapez sortie))
//déclarations
Noter les positions des données d'entrée et de sortie aux différents endroits du pseudo-code. L'entrée de la fonction de rappel est sa sortie. Les paramètres de la fonction principale sont le paramètre d'entrée du code général et le paramètre de la fonction de rappel. Avec ce schéma, une troisième fonction peut être exécutée (appelée) dans la fonction main() avant que la sortie de la fonction de rappel ne soit lue (toujours dans la fonction main()). Le code suivant illustre cela :
#inclureen utilisant l'espace de noms std ;
char *sortie;
void cb(char out[])
sortie = sortie ;
void principalFn(char input[], void (*ptr)(char[50]))
(*ptr)(entrée);
cout<<"principal function"<<'\n';
vide fn()
cout<<"seen"<<'\n';
int main()
char input[] = "fonction de rappel" ;
void (*ptr)(char[]) = &cb;
principalFn(entrée, cb);
fn();
cout<