C ++

Função de retorno de chamada em C ++

Função de retorno de chamada em C ++

Uma função de retorno de chamada é uma função, que é um argumento, não um parâmetro, em outra função. A outra função pode ser chamada de função principal. Portanto, duas funções estão envolvidas: a função principal e a própria função de retorno de chamada. Na lista de parâmetros da função principal, a declaração da função de retorno de chamada sem sua definição está presente, assim como as declarações de objeto sem atribuição estão presentes. A função principal é chamada com argumentos (em main ()). Um dos argumentos na chamada da função principal é a definição efetiva da função de retorno de chamada. Em C ++, esse argumento é uma referência à definição da função de retorno de chamada; não é a definição real. A própria função de retorno de chamada é realmente chamada dentro da definição da função principal.

A função de retorno de chamada básica em C ++ não garante comportamento assíncrono em um programa.  O comportamento assíncrono é o benefício real do esquema de função de retorno de chamada. No esquema de função de retorno de chamada assíncrona, o resultado da função principal deve ser obtido para o programa antes que o resultado da função de retorno de chamada seja obtido. É possível fazer isso em C ++; no entanto, C ++ tem uma biblioteca chamada future para garantir o comportamento do esquema de função de retorno de chamada assíncrona.

Este artigo explica o esquema básico da função de retorno de chamada. Muito disso é com C puro++. No que diz respeito ao retorno de chamada, o comportamento básico da futura biblioteca também é explicado. O conhecimento básico de C ++ e seus indicadores são necessários para a compreensão deste artigo.

Conteúdo do Artigo

Esquema de função de retorno de chamada básico

Um esquema de função de retorno de chamada precisa de uma função principal, e a própria função de retorno de chamada. A declaração da função de retorno de chamada faz parte da lista de parâmetros da função principal. A definição da função de retorno de chamada é indicada na chamada de função da função principal. A função de retorno de chamada é realmente chamada dentro da definição da função principal. O programa a seguir ilustra isso:

#incluir
usando namespace std;
int principalFn (char ch [], int (* ptr) (int))

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

int cb (int iden)

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

int main ()

int (* ptr) (int) = &cb;
char cha [] = "e";
principalFn (cha, cb);
return 0;

O resultado é:

função de retorno de chamada
função principal: 1 e 2

A função principal é identificada por principalFn (). A função de retorno de chamada é identificada por cb (). A função de retorno de chamada é definida fora da função principal, mas na verdade é chamada dentro da função principal.

Observe a declaração da função de retorno de chamada como um parâmetro na lista de parâmetros da declaração da função principal. A declaração da função de retorno de chamada é “int (* ptr) (int)”. Observe a expressão da função de retorno de chamada, como uma chamada de função, na definição da função principal; qualquer argumento para a chamada da função de retorno de chamada é passado lá. A instrução para esta chamada de função é:

int idr = (* ptr) (id2);

Onde id2 é um argumento. ptr faz parte do parâmetro, um ponteiro, que será vinculado à referência da função de retorno de chamada na função main ().

Observe a expressão:

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

Na função main (), que vincula a declaração (sem definição) da função de retorno de chamada ao nome da definição da mesma função de retorno de chamada.

A função principal é chamada, na função main (), como:

principalFn (cha, cb);

Onde cha é uma string e cb é o nome da função de retorno de chamada sem nenhum de seus argumentos.

Comportamento síncrono da função de retorno de chamada

Considere o seguinte programa:

#incluir
usando namespace std;
void principalFn (void (* ptr) ())

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

void cb ()

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

void fn ()

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

int main ()

void (* ptr) () = &cb;
principalFn (cb);
fn ();
return 0;

O resultado é:

função principal
função de retorno de chamada
visto

Há uma nova função aqui. Tudo o que a nova função faz é exibir a saída, "visto". Na função main (), a função principal é chamada, então a nova função, fn () é chamada. A saída mostra que o código para a função principal foi executado, depois o da função de retorno de chamada e, finalmente, o da função fn (). Este é um comportamento síncrono (single-threaded).

Se fosse um comportamento assíncrono, quando três segmentos de código são chamados em ordem, o primeiro segmento de código pode ser executado, seguido pela execução do terceiro segmento de código, antes que o segundo segmento de código seja executado.

Bem, a função, fn () pode ser chamada de dentro da definição da função principal, em vez de dentro da função main (), da seguinte maneira:

#incluir
usando namespace std;
void fn ()

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

void principalFn (void (* ptr) ())

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

void cb ()

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

int main ()

void (* ptr) () = &cb;
principalFn (cb);
return 0;

O resultado é:

função principal
visto
função de retorno de chamada

Esta é uma imitação de comportamento assíncrono. Não é um comportamento assíncrono. Ainda é um comportamento síncrono.

Além disso, a ordem de execução do segmento de código da função principal e o segmento de código da função de retorno de chamada podem ser trocados na definição da função principal. O programa a seguir ilustra isso:

#incluir
usando namespace std;
 
void principalFn (void (* ptr) ())

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

void cb ()

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

void fn ()

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

int main ()

void (* ptr) () = &cb;
principalFn (cb);
fn ();
return 0;

A saída é agora,

função de retorno de chamada
função principal
visto

Isso também é uma imitação do comportamento assíncrono. Não é um comportamento assíncrono. Ainda é um comportamento síncrono. O comportamento assíncrono verdadeiro pode ser obtido conforme explicado na próxima seção ou com a biblioteca, no futuro.

Comportamento assíncrono com função de retorno de chamada

O pseudocódigo para o esquema básico de função de retorno de chamada assíncrona é:

saída de tipo;
tipo cb (tipo de saída)

//afirmações

tipo principalFn (tipo de entrada, tipo cb (tipo de saída))

//afirmações

Observe as posições dos dados de entrada e saída nos diferentes lugares do pseudo-código. A entrada da função de retorno de chamada é sua saída. Os parâmetros da função principal são o parâmetro de entrada para o código geral e o parâmetro para a função de retorno de chamada. Com este esquema, uma terceira função pode ser executada (chamada) na função main () antes que a saída da função callback seja lida (ainda na função main ()). O código a seguir ilustra isso:

#incluir
usando namespace std;
saída char *;
void cb (char out [])

output = out;

void principalFn (char input [], void (* ptr) (char [50]))

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

void fn ()

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

int main ()

entrada char [] = "função de retorno de chamada";
void (* ptr) (char []) = &cb;
principalFn (entrada, cb);
fn ();
cout<return 0;

O resultado do programa é:

função principal
visto
função de retorno de chamada

Neste código em particular, os dados de saída e entrada são os mesmos. O resultado da terceira chamada de função na função main () foi exibido antes do resultado da função de retorno de chamada. A função de retorno de chamada foi executada, finalizada e atribuída seu resultado (valor) à variável de saída, permitindo que o programa continue sem sua interferência. Na função main (), a saída da função de retorno de chamada foi usada (lida e exibida) quando necessário, levando a um comportamento assíncrono para todo o esquema.

Esta é a maneira de single-threaded para obter o comportamento assíncrono da função de retorno de chamada com C puro++.

Uso básico da futura Biblioteca

A ideia do esquema de função de retorno de chamada assíncrona é que a função principal retorna antes que a função de retorno de chamada retorne. Isso foi feito indiretamente, de forma eficaz, no código acima.

Observe no código acima que a função de retorno de chamada recebe a entrada principal para o código e produz a saída principal para o código. A biblioteca C ++, futura, tem uma função chamada sync (). O primeiro argumento para esta função é a referência da função de retorno de chamada; o segundo argumento é a entrada para a função de retorno de chamada. A função sync () retorna sem esperar que a execução da função de retorno de chamada seja concluída, mas permite que a função de retorno de chamada seja concluída. Isso fornece comportamento assíncrono. Enquanto a função de retorno de chamada continua a ser executada, uma vez que a função sync () já retornou, as instruções abaixo dela continuam a ser executadas. É como um comportamento assíncrono ideal.

O programa acima foi reescrito abaixo, levando em consideração a futura biblioteca e sua função sync ():

#incluir
#incluir
#incluir
usando namespace std;
futuro resultado;
string cb (string stri)

return stri;

void principalFn (entrada de string)

saída = assíncrona (cb, entrada);
cout<<"principal function"<<'\n';

void fn ()

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

int main ()

string input = string ("função de retorno de chamada");
principalFn (entrada);
fn ();
string ret = output.obter(); // aguarda o retorno de chamada para retornar, se necessário
cout<return 0;

A função sync () finalmente armazena a saída da função de retorno de chamada no objeto futuro. A saída esperada pode ser obtida na função main (), usando a função membro get () do objeto futuro.

Conclusão

Uma função de retorno de chamada é uma função, que é um argumento, não um parâmetro, em outra função. Um esquema de função de retorno de chamada precisa de uma função principal, e a própria função de retorno de chamada. A declaração da função de retorno de chamada faz parte da lista de parâmetros da função principal. A definição da função de retorno de chamada é indicada na chamada de função da função principal (em main ()). A função de retorno de chamada é realmente chamada dentro da definição da função principal.

Um esquema de função de retorno de chamada não é necessariamente assíncrono. Para ter certeza de que o esquema da função de retorno de chamada é assíncrono, faça a entrada principal para o código, a entrada para a função de retorno de chamada; fazer a saída principal do código, a saída da função de retorno de chamada; armazenar a saída da função de retorno de chamada em uma variável ou estrutura de dados. Na função main (), depois de chamar a função principal, execute outras instruções do aplicativo. Quando a saída da função de retorno de chamada é necessária, na função main (), use (leia e exiba) lá e então.

Tutorial OpenTTD
OpenTTD é um dos jogos de simulação de negócios mais populares que existem. Neste jogo, você precisa criar um maravilhoso negócio de transporte. No en...
SuperTuxKart para Linux
SuperTuxKart é um ótimo título projetado para trazer a você a experiência Mario Kart gratuitamente em seu sistema Linux. É bastante desafiador e diver...
Tutorial de Battle for Wesnoth
The Battle for Wesnoth é um dos jogos de estratégia de código aberto mais populares que você pode jogar no momento. Este jogo não está apenas em desen...