Función de devolución de llamada en C ++

Función de devolución de llamada en C ++

Una función de devolución de llamada es una función, que es un argumento, no un parámetro, en otra función. La otra función puede llamarse la función principal. Entonces están involucradas dos funciones: la función principal y la función de devolución de llamada misma. En la lista de parámetros de la función principal, la declaración de la función de devolución de llamada sin su definición está presente, al igual que las declaraciones de objetos sin asignación están presentes. La función principal se llama con argumentos (en main ()). Uno de los argumentos en la llamada de la función principal es la definición efectiva de la función de devolución de llamada. En C ++, este argumento es una referencia a la definición de la función de devolución de llamada; No es la definición real. La función de devolución de llamada en sí misma se llama dentro de la definición de la función principal.

La función básica de devolución de llamada en C ++ no garantiza el comportamiento asincrónico en un programa. El comportamiento asincrónico es el beneficio real del esquema de función de devolución de llamada. En el esquema de función de devolución de llamada asincrónica, el resultado de la función principal debe obtenerse para el programa antes de obtener el resultado de la función de devolución de llamada. Es posible hacer esto en C ++; Sin embargo, C ++ tiene una biblioteca llamada Future para garantizar el comportamiento del esquema de función de devolución de llamada asíncrona.

Este artículo explica el esquema de función de devolución de llamada básica. Mucho de eso es con pu pure++. En lo que respecta a la devolución de llamada, el comportamiento básico de la biblioteca futura también se explica. El conocimiento básico de C ++ y sus punteros es necesario para la comprensión de este artículo.

Contenido del artículo

  • Esquema de función de devolución de llamada básica
  • Comportamiento sincrónico con la función de devolución de llamada
  • Comportamiento asincrónico con función de devolución de llamada
  • Uso básico de la biblioteca futura
  • Conclusión

Esquema de función de devolución de llamada básica

Un esquema de función de devolución de llamada necesita una función principal, y la función de devolución de llamada misma. La declaración de la función de devolución de llamada es parte de la lista de parámetros de la función principal. La definición de la función de devolución de llamada se indica en la llamada de función de la función principal. La función de devolución de llamada en realidad se llama dentro de la definición de la función principal. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres STD;
int principalfn (charch [], int (*ptr) (int))

int id1 = 1;
int id2 = 2;
int idr = (*ptr) (id2);
cout<<"principal function: "<<
ID1<<"<return id1;

int cb (int iden)

cout<<"callback function"<<'\n';
devolver IDEN;

int main ()

int (*ptr) (int) = &cb;
char cha [] = "y";
principalfn (cha, cb);
regresar 0;

La salida es:

función de devolución de llamada
Función principal: 1 y 2

La función principal se identifica por principal (). La función de devolución de llamada se identifica por CB (). La función de devolución de llamada se define fuera de la función principal, pero en realidad se llama dentro de la función principal.

Tenga en cuenta la declaración de la función de devolución de llamada como un parámetro en la lista de parámetros de la Declaración de la función principal. La declaración de la función de devolución de llamada es "int (*ptr) (int)". Tenga en cuenta la expresión de la función de devolución de llamada, como una llamada de función, en la definición de la función principal; Cualquier argumento para la llamada de devolución de llamada se pasa allí. La declaración para esta llamada de función es:

int idr = (*ptr) (id2);

Donde ID2 es un argumento. PTR es parte del parámetro, un puntero, que estará vinculado a la referencia de la función de devolución de llamada en la función Main ().

Tenga en cuenta la expresión:

int (*ptr) (int) = &cb;

En la función main (), que vincula la declaración (sin definición) de la función de devolución de llamada al nombre de la definición de la misma función de devolución de llamada.

La función principal se llama, en la función principal (), como:

principalfn (cha, cb);

Donde cha es una cadena y CB es el nombre de la función de devolución de llamada sin ninguno de sus argumentos.

Comportamiento sincrónico de la función de devolución de llamada

Considere el siguiente programa:

#incluir
usando el espacio de nombres STD;
nulo principal (void (*ptr) ())

cout<<"principal function"<<'\n';
(*ptr) ();

void cb ()

cout<<"callback function"<<'\n';

nulo fn ()

cout<<"seen"<<'\n';

int main ()

void (*ptr) () = &cb;
principalfn (CB);
fn ();
regresar 0;

La salida es:

función principal
función de devolución de llamada
visto

Hay una nueva función aquí. Todo lo que hace la nueva función es mostrar la salida, "visto". En la función main (), se llama la función principal, entonces se llama a la nueva función, fn (). La salida muestra que se ejecutó el código para la función principal, luego que para la función de devolución de llamada se ejecutó, y finalmente que para la función fn () se ejecutó. Este es un comportamiento sincrónico (de un solo hilo).

Si fuera un comportamiento asincrónico, cuando se llaman a tres segmentos de código en orden, el primer segmento de código se puede ejecutar, seguido en su lugar por la ejecución del tercer segmento de código, antes de que se ejecute el segundo segmento de código.

Bueno, la función, fn () se puede llamar desde la definición de la función principal, en lugar de desde la función main (), como sigue:

#incluir
usando el espacio de nombres STD;
nulo fn ()

cout<<"seen"<<'\n';

nulo principal (void (*ptr) ())

cout<<"principal function"<<'\n';
fn ();
(*ptr) ();

void cb ()

cout<<"callback function"<<'\n';

int main ()

void (*ptr) () = &cb;
principalfn (CB);
regresar 0;

La salida es:

función principal
visto
función de devolución de llamada

Esta es una imitación del comportamiento asincrónico. No es un comportamiento asincrónico. Sigue siendo un comportamiento sincrónico.

Además, el orden de ejecución del segmento de código de la función principal y el segmento de código de la función de devolución de llamada se puede cambiar en la definición de la función principal. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres STD;
nulo principal (void (*ptr) ())

(*ptr) ();
cout<<"principal function"<<'\n';

void cb ()

cout<<"callback function"<<'\n';

nulo fn ()

cout<<"seen"<<'\n';

int main ()

void (*ptr) () = &cb;
principalfn (CB);
fn ();
regresar 0;

La salida es ahora,

función de devolución de llamada
función principal
visto

Esto también es una imitación del comportamiento asincrónico. No es un comportamiento asincrónico. Sigue siendo un comportamiento sincrónico. El verdadero comportamiento asincrónico se puede obtener como se explica en la siguiente sección o con la biblioteca, futuro.

Comportamiento asincrónico con función de devolución de llamada

El pseudocódigo para el esquema básico de función de devolución de llamada asincrónica es:

Tipo de salida;
Tipo CB (Tipo de salida)

//declaraciones

Tipo principalfn (tipo de entrada, tipo CB (salida de tipo))

//declaraciones

Tenga en cuenta las posiciones de los datos de entrada y salida en los diferentes lugares del código de pseudo. La entrada de la función de devolución de llamada es su salida. Los parámetros de la función principal son el parámetro de entrada para el código general y el parámetro para la función de devolución de llamada. Con este esquema, se puede ejecutar una tercera función (llamada) en la función main () antes de que se lea la salida de la función de devolución de llamada (todavía en la función main ()). El siguiente código ilustra esto:

#incluir
usando el espacio de nombres STD;
char *salida;
Vacío CB (Char Out [])

salida = out;

void principalfn (char entrada [], void (*ptr) (char [50]))

(*ptr) (entrada);
cout<<"principal function"<<'\n';

nulo fn ()

cout<<"seen"<<'\n';

int main ()

char entrada [] = "función de devolución de llamada";
void (*ptr) (char []) = &cb;
principalfn (entrada, CB);
fn ();
cout<regresar 0;

La salida del programa es:

función principal
visto
función de devolución de llamada

En este código en particular, la salida y el dato de entrada son el mismo dato. El resultado de la tercera llamada de función en la función Main () se ha mostrado antes del resultado de la función de devolución de llamada. La función de devolución de llamada ejecutada, terminada y asignada su resultado (valor) a la variable, la salida, lo que permite que el programa continúe sin su interferencia. En la función Main (), la salida de la función de devolución de llamada se usó (leída y se muestra) cuando era necesaria, lo que lleva a un comportamiento asincrónico para todo el esquema.

Esta es la forma única de obtener el comportamiento asíncrono de la función de devolución de llamada con C pura C++.

Uso básico de la biblioteca futura

La idea del esquema de función de devolución de llamada asincrónica es que la función principal regresa antes de que regrese la función de devolución de llamada. Esto se hizo indirectamente, efectivamente, en el código anterior.

Tenga en cuenta del código anterior que la función de devolución de llamada recibe la entrada principal para el código y produce la salida principal para el código. La biblioteca C ++, Future, tiene una función llamada Sync (). El primer argumento de esta función es la referencia de la función de devolución de llamada; El segundo argumento es la entrada a la función de devolución de llamada. La función sinc () regresa sin esperar la ejecución de la función de devolución de llamada para completar pero permite que la función de devolución de llamada se complete. Esto proporciona un comportamiento asincrónico. Mientras la función de devolución de llamada continúa ejecutándose, ya que la función sinc () ya ha regresado, las declaraciones a continuación continúan ejecutando. Esto es como un comportamiento asincrónico ideal.

El programa anterior se ha reescrito a continuación, teniendo en cuenta, la Future Library y su función Sync ():

#incluir
#incluir
#incluir
usando el espacio de nombres STD;
futuro producción;
String CB (String STRI)

regresar stri;

nulo principalfn (entrada de cadena)

salida = async (cb, entrada);
cout<<"principal function"<<'\n';

nulo fn ()

cout<<"seen"<<'\n';

int main ()

String input = string ("función de devolución de llamada");
principalfn (entrada);
fn ();
cadena retir = salida.conseguir(); // espera a que devuelva la devolución de llamada si es necesario
cout<regresar 0;

La función sinc () finalmente almacena la salida de la función de devolución de llamada en el objeto futuro. La salida esperada se puede obtener en la función main (), utilizando la función miembro get () del objeto futuro.

Conclusión

Una función de devolución de llamada es una función, que es un argumento, no un parámetro, en otra función. Un esquema de función de devolución de llamada necesita una función principal, y la función de devolución de llamada misma. La declaración de la función de devolución de llamada es parte de la lista de parámetros de la función principal. La definición de la función de devolución de llamada se indica en la llamada de función de la función principal (en main ()). La función de devolución de llamada en realidad se llama dentro de la definición de la función principal.

Un esquema de función de devolución de llamada no es necesariamente asíncrono. Para asegurarse de que el esquema de función de devolución de llamada sea asíncrono, realice la entrada principal al código, la entrada a la función de devolución de llamada; hacer la salida principal del código, la salida de la función de devolución de llamada; almacenar la salida de la función de devolución de llamada en una estructura variable o de datos. En la función main (), después de llamar a la función principal, ejecute otras declaraciones de la aplicación. Cuando se necesita la salida de la función de devolución de llamada, en la función Main (), use (lea y visualiza) allí y luego.