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 principal função 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 objetos sem atribuição estão presentes. A função principal é chamada com argumentos (em main ()). Um dos argumentos na chamada de 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 função de retorno de chamada em si é realmente chamada na definição da função principal.
A função básica de retorno de chamada em C ++ não garante comportamento assíncrono em um programa. O comportamento assíncrono é o verdadeiro benefício do esquema de função de retorno de chamada. No esquema de função de retorno de chamada assíncrono, 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, o 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 de função de retorno de chamada. Muito disso é com p 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 ponteiros é necessário para a compreensão deste artigo.
Conteúdo do artigo
Esquema básico de função de retorno de chamada
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 na definição da função principal. O programa a seguir ilustra o seguinte:
#incluir
usando namespace std;
Int Principalfn (char ch [], int (*ptr) (int))
int id1 = 1;
int id2 = 2;
int idr = (*ptr) (id2);
cout<<"principal function: "<<
id1<<"<retornar id1;
int cb (int iden)
cout<<"callback function"<<'\n';
retornar iden;
int main ()
int (*ptr) (int) = &cb;
char cha [] = "e";
Principalfn (CHA, CB);
retornar 0;
A saída é:
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 na 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 de função de retorno de chamada é passado lá. A declaraçã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 principal ().
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 o CHA é uma string e CB é o nome da função de retorno de chamada sem nenhum de seu argumento.
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 ();
retornar 0;
A saída é:
Função principalHá uma nova função aqui. Toda a nova função faz, é exibir a saída "vista". Na função main (), a principal função é chamada, então a nova função, fn () é chamada. A saída mostra que o código da função principal foi executado, então que a função de retorno de chamada foi executada e, finalmente, a função fn () foi executada. Este é um comportamento síncrono (thread único).
Se fosse um comportamento assíncrono, quando três segmentos de código são chamados em ordem, o primeiro segmento de código poderá 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 forma:
#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);
retornar 0;
A saída é:
Função principalIsso é 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 o seguinte:
#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 ();
retornar 0;
A saída é agora,
função de retorno de chamadaIsso também é uma imitação de comportamento assíncrono. Não é um comportamento assíncrono. Ainda é um comportamento síncrono. O verdadeiro comportamento assíncrono pode ser obtido conforme explicado na próxima seção ou com a biblioteca, futuro.
Comportamento assíncrono com função de retorno de chamada
O código pseudo para o esquema básico de função de retorno de chamada assíncrona é:
saída de tipo;
Tipo CB (saída do tipo)
//declarações
Tipo Principalfn (Tipo de entrada, tipo CB (saída de tipo))
//declarações
Observe as posições dos dados de entrada e saída nos diferentes locais 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 principal () antes da saída da função de retorno de chamada (ainda na função principal ()). O código a seguir ilustra o seguinte:
#incluir
usando namespace std;
Char *saída;
Void CB (char out [])
saída = out;
Void Principalfn (Char Input [], void (*ptr) (char [50]))
(*ptr) (entrada);
cout<<"principal function"<<'\n';
void fn ()
cout<<"seen"<<'\n';
int main ()
char input [] = "Função de retorno de chamada";
void (*ptr) (char []) = &cb;
Principalfn (entrada, CB);
fn ();
cout<
A saída do programa é:
Função principalNeste código em particular, a saída e a entrada de dados são o mesmo dado. O resultado da terceira chamada de função na função principal () foi exibida antes do resultado da função de retorno de chamada. A função de retorno de chamada executada, finalizada e atribuiu seu resultado (valor) à variável, 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 única de obter uma função de retorno de chamada com comportamento assíncrono com puro C++.
Uso básico da futura biblioteca
A idéia 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, efetivamente, no código acima.
Nota do código acima que a função de retorno de chamada recebe a entrada principal do código e produz a saída principal para o código. A biblioteca C ++, Future, 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 a execução da função de retorno de chamada ser 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 executar, como a função Sync () já retornou, as declarações abaixo continuam a executar. É como um comportamento assíncrono ideal.
O programa acima foi reescrito abaixo, levando em consideração, a Future Library e sua função Sync ():
#incluir
#incluir
#incluir
usando namespace std;
futurosaída;
String CB (String Stri)
retornar stri;
Void Principalfn (entrada da string)
saída = assíncrono (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 = saída.pegar(); // aguarda o retorno de chamada, se necessário
cout<retornar 0;
A função SYNC () finalmente armazena a saída da função de retorno de chamada no futuro objeto. A saída esperada pode ser obtida na função principal (), usando a função get () membro 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 na 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 de 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; Faça a saída principal do código, a saída da função de retorno de chamada; Armazene 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 declarações do aplicativo. Quando a saída da função de retorno de chamada é necessária, na função principal (), use (leia e exiba) lá e depois.