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

Callback Function 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 o 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 namespacehoras;



intmainFn(CaracteresCH[],int (*ptr)(int))

{

intid1= 1;

intid2= 2;

intusualmente= (*ptr)(id2);

custo<<'função principal:'<<id1<<''<<CH<<''<<usualmente<<' n';

Retornaid1;

}


intcb(intiden)

{

custo<<'função callback'<<' n';

Retornaiden;

}


inta Principal()

{

int (*ptr)(int) = Ecb;

Caracteresnão[] = 'e';

mainFn(pai, cb);



Retorna 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 de função de retorno de chamada é passado lá. A instrução para esta chamada de função é:



intusualmente= (*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) = Ecb;

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:

mainFn(pai, 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 namespacehoras;



vaziomainFn(vazio (*ptr)())

{

custo<<'função principal'<<' n';

(*ptr)();

}


vaziocb()

{

custo<<'função callback'<<' n';

}


vaziofn()

{

custo<<'visto'<<' n';

}


inta Principal()

{

vazio (*ptr)() = Ecb;

mainFn(cb);

fn();



Retorna 0;

}

O resultado é:

função principal

função de retorno de chamada

visto

Existe uma nova função aqui. Tudo o que a nova função faz é exibir a saída, vista. Na função main (), a função principal é chamada e, em seguida, 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 é o 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 namespacehoras;



vaziofn()

{

custo<<'visto'<<' n';

}


vaziomainFn(vazio (*ptr)())

{

custo<<'função principal'<<' n';

fn();

(*ptr)();

}


vaziocb()

{

custo<<'função callback'<<' n';

}


inta Principal()

{

vazio (*ptr)() = Ecb;

mainFn(cb);



Retorna 0;

}

O resultado é:

função principal

visto

função de retorno de chamada

Esta é uma imitação do 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 namespacehoras;



vaziomainFn(vazio (*ptr)())

{

(*ptr)();

custo<<'função principal'<<' n';

}


vaziocb()

{

custo<<'função callback'<<' n';

}


vaziofn()

{

custo<<'visto'<<' n';

}


inta Principal()

{

vazio (*ptr)() = Ecb;

mainFn(cb);

fn();



Retorna 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;

digite cb(saída de tipo)

{

//afirmações

}


tipo principalFn(digite input, digite cb(saída de tipo))

{

//afirmações

}

Observe as posições dos dados de entrada e saída nos diferentes lugares do pseudocó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 esse esquema, uma terceira função pode ser executada (chamada) na função main () antes que a saída da função de retorno de chamada seja lida (ainda na função main ()). O código a seguir ilustra isso:

#incluir

usando namespacehoras;

Caracteres *saída;


vaziocb(CaracteresFora[])

{

saída=Fora;

}



vaziomainFn(Caracteresentrada[],vazio (*ptr)(Caracteres[cinquenta]))

{

(*ptr)(entrada);

custo<<'função principal'<<' n';

}


vaziofn()

{

custo<<'visto'<<' n';

}


inta Principal()

{

Caracteresentrada[] = 'função callback';

vazio (*ptr)(Caracteres[]) = Ecb;

mainFn(entrada, cb);

fn();

custo<<saída<<' n';



Retorna 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 de 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 executou, finalizou e atribuiu 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.

Essa é a maneira de thread único de 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 retorne antes do retorno da função de retorno de chamada. Isso foi feito indiretamente, efetivamente, 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. Isso é 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 namespacehoras;

futuro<fragmento>saída;

string cb(string stri)

{

Retornastri;

}



vaziomainFn(entrada de string)

{

saída=assíncrono(cb, entrada);

custo<<'função principal'<<' n';

}


vaziofn()

{

custo<<'visto'<<' n';

}


inta Principal()

{

entrada de string=fragmento('função callback');

mainFn(entrada);

fn();

string ret=saída.pegue(); // aguarda o retorno de chamada para retornar, se necessário

custo<<direito<<' n';



Retorna 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 for necessária, na função main (), use (leia e exiba) lá e então.