Funkcja wywołania zwrotnego w C ++

Funkcja wywołania zwrotnego w C ++

Funkcja wywołania zwrotnego jest funkcją, która jest argumentem, a nie parametrem, w innej funkcji. Drugą funkcję można nazwać główną funkcją. Tak więc zaangażowane są dwie funkcje: główna funkcja i sama funkcja wywołania zwrotnego. Na liście parametrów funkcji głównej, deklaracja funkcji wywołania zwrotnego bez jej definicji jest obecna, podobnie jak deklaracje obiektowe bez przypisania. Główna funkcja jest wywoływana z argumentami (w main ()). Jednym z argumentów w głównym wywołaniu funkcji jest skuteczna definicja funkcji wywołania zwrotnego. W C ++ ten argument jest odniesieniem do definicji funkcji wywołania zwrotnego; To nie jest faktyczna definicja. Sama funkcja wywołania zwrotnego jest faktycznie wywoływana w definicji funkcji głównej.

Podstawowa funkcja wywołania zwrotnego w C ++ nie gwarantuje zachowania asynchronicznego w programie. Zachowanie asynchroniczne jest prawdziwą korzyścią z schematu funkcji zwrotnej. W asynchronicznym schemacie funkcji wywołania zwrotnego wynik głównej funkcji należy uzyskać dla programu przed uzyskaniem wyniku funkcji wywołania zwrotnego. Można to zrobić w C ++; Jednak C ++ ma bibliotekę o nazwie Future, aby zagwarantować zachowanie asynchronicznego schematu funkcji wywołania zwrotnego.

W tym artykule wyjaśniono podstawowy schemat funkcji zwrotnej. Wiele z nich jest z czystym c++. Jeśli chodzi o wywołanie zwrotne, wyjaśniono również podstawowe zachowanie przyszłej biblioteki. Podstawowa znajomość C ++ i jego wskaźniki jest niezbędne do zrozumienia tego artykułu.

Treść artykułu

  • Podstawowy schemat funkcji zwrotnej
  • Synchroniczne zachowanie z funkcją wywołania zwrotnego
  • Zachowanie asynchroniczne z funkcją wywołania zwrotnego
  • Podstawowe użycie przyszłej biblioteki
  • Wniosek

Podstawowy schemat funkcji zwrotnej

Schemat funkcji wywoławczy wymaga głównej funkcji i samej funkcji wywołania zwrotnego. Deklaracja funkcji zwrotnej jest częścią listy parametrów funkcji głównej. Definicja funkcji wywołania zwrotnego jest wskazana w wywołaniu funkcji funkcji głównej. Funkcja wywołania zwrotnego jest faktycznie wywoływana w definicji funkcji głównej. Poniższy program ilustruje to:

#włączać
za pomocą przestrzeni nazw Std;
int cointalfn (char ch [], 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';
powrót iden;

int main ()

int (*ptr) (int) = &cb;
Char Cha [] = "i";
Principalfn (CHA, CB);
powrót 0;

Wyjście to:

Funkcja zwrotnego
Główna funkcja: 1 i 2

Funkcja główna jest identyfikowana przez Principalfn (). Funkcja wywołania zwrotnego jest identyfikowana przez CB (). Funkcja wywołania zwrotnego jest zdefiniowana poza funkcją główną, ale faktycznie wywoływaną w funkcji głównej.

Zwróć uwagę na deklarację funkcji zwrotnej jako parametr na liście parametrów deklaracji funkcji głównej. Deklaracja funkcji wywołania zwrotnego to „int (*ptr) (int)”. Zwróć uwagę na wyrażenie funkcji zwrotnej, podobnie jak wywołanie funkcji, w definicji funkcji głównej; Przekazano tam każdy argument dotyczący wywołania funkcji zwrotnej. Instrukcja tego wywołania funkcji jest:

int IDR = (*ptr) (id2);

Gdzie ID2 jest argumentem. PTR jest częścią parametru, wskaźnika, który zostanie powiązany z odniesieniem funkcji wywołania zwrotnego w funkcji Main (.

Zwróć uwagę na wyrażenie:

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

W funkcji main (), która łączy deklarację (bez definicji) funkcji wywołania zwrotnego do nazwy definicji tej samej funkcji zwrotnej.

Główna funkcja jest wywoływana w funkcji Main () jako:

Principalfn (CHA, CB);

Gdzie cha jest ciągiem, a CB to nazwa funkcji wywołania zwrotnego bez żadnego argumentu.

Synchroniczne zachowanie funkcji wywołania zwrotnego

Rozważ następujący program:

#włączać
za pomocą przestrzeni nazw 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 ();
powrót 0;

Wyjście to:

główna funkcja
Funkcja zwrotnego
widziany

Jest tutaj nowa funkcja. Cała nowa funkcja to wyświetlanie danych wyjściowych „widzianych”. W funkcji main () funkcja główna jest wywoływana, a następnie nowa funkcja, fn () jest wywoływana. Dane wyjściowe pokazuje, że wykonano kod funkcji głównej, a następnie wykonano funkcję zwrotną, a na koniec wykonano funkcję FN (. Jest to zachowanie synchroniczne (jednoosobowe).

Jeśli było to zachowanie asynchroniczne, gdy w kolejności wywołane są trzy segmenty kodu, pierwszy segment kodu może zostać wykonany, a następnie wykonanie trzeciego segmentu kodu, przed wykonaniem drugiego segmentu kodu.

Cóż, funkcję, fn () można wywołać z definicji funkcji głównej, zamiast z funkcji Main (), jak następuje:

#włączać
za pomocą przestrzeni nazw 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);
powrót 0;

Wyjście to:

główna funkcja
widziany
Funkcja zwrotnego

To imitacja zachowań asynchronicznych. To nie jest zachowanie asynchroniczne. To wciąż jest synchroniczne.

Również kolejność wykonywania segmentu kodu funkcji głównej i segmentu kodu funkcji wywołania zwrotnego można zamienić w definicji funkcji głównej. Poniższy program ilustruje to:

#włączać
za pomocą przestrzeni nazw 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 ();
powrót 0;

Wyjście jest teraz,

Funkcja zwrotnego
główna funkcja
widziany

Jest to również naśladowanie zachowań asynchronicznych. To nie jest zachowanie asynchroniczne. To wciąż jest synchroniczne. Prawdziwe zachowanie asynchroniczne można uzyskać, jak wyjaśniono w następnej sekcji lub z biblioteką, przyszłość.

Zachowanie asynchroniczne z funkcją wywołania zwrotnego

Pseudo-kod dla podstawowego asynchronicznego schematu funkcji wywołania zwrotnego jest:

Wyjście typu;
Wpisz CB (typ wyjścia)

//sprawozdania

Typ Principalfn (Typ Input, Typ Cb (typ wyjściowy))

//sprawozdania

Zwróć uwagę na pozycje danych wejściowych i wyjściowych w różnych miejscach pseudo-kodu. Wejście funkcji wywoławczej jest jego wyjście. Parametry funkcji głównej to parametr wejściowy dla kodu ogólnego i parametr funkcji zwrotnej. W tym schemacie można wykonać trzecią funkcję (wywołaną) w funkcji Main (), zanim wyjście funkcji wywołania zwrotnego zostanie odczytane (wciąż w funkcji Main ()). Poniższy kod to ilustruje:

#włączać
za pomocą przestrzeni nazw Std;
Char *wyjście;
Void CB (Char Out [])

wyjście = out;

void Principalfn (Char Input [], void (*ptr) (char [50]))

(*ptr) (wejście);
Cout<<"principal function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

char input [] = "funkcja callback";
void (*ptr) (char []) = &cb;
Principalfn (wejście, CB);
fn ();
Cout<powrót 0;

Wyjście programu to:

główna funkcja
widziany
Funkcja zwrotnego

W tym konkretnym kodzie wyjście i wejściowe odniesie. Wynik trzeciego wywołania funkcji w funkcji Main () został wyświetlony przed wynikiem funkcji wywołania zwrotnego. Funkcja wywołania zwrotnego wykonana, zakończona i przypisała jej wynik (wartość) do zmiennej, wyjściu, umożliwiając programowi kontynuowanie bez jego zakłóceń. W funkcji Main () zastosowano dane wyjściowe funkcji wywołania zwrotnego (odczyt i wyświetlanie), gdy było jej potrzebne, co prowadzi do zachowania asynchronicznego dla całego schematu.

Jest to jednoosobowy sposób uzyskania zachowania asynchronicznego funkcji wywołania zwrotnego z czystym C++.

Podstawowe użycie przyszłej biblioteki

Idea asynchronicznego schematu funkcji wywołania zwrotnego polega na tym, że główna funkcja powraca przed powrót funkcji wywołania zwrotnego. Dokonano tego pośrednio, skutecznie, w powyższym kodzie.

Uwaga z powyższego kodu, że funkcja zwrotu odbiorczy odbiera główne wejście dla kodu i tworzy główne dane wyjściowe dla kodu. Biblioteka C ++, Future, ma funkcję o nazwie Sync (). Pierwszym argumentem tej funkcji jest odniesienie funkcji zwrotnej; Drugim argumentem jest wejście do funkcji wywołania zwrotnego. Funkcja sync () zwraca bez oczekiwania na zakończenie funkcji wywołania zwrotnego, ale umożliwia zakończenie funkcji wywołania zwrotnego. Zapewnia to asynchroniczne zachowanie. Podczas gdy funkcja wywołania zwrotnego nadal wykonuje się, ponieważ funkcja synchronizacji () już zwróciła, stwierdzenia poniżej nadal wykonują. To jest idealne zachowanie asynchroniczne.

Powyższy program został przepisany poniżej, biorąc pod uwagę przyszłą bibliotekę i jej funkcję Sync ():

#włączać
#włączać
#włączać
za pomocą przestrzeni nazw Std;
przyszły wyjście;
String CB (String Stri)

powrót stri;

void Principalfn (wejście ciągów)

wyjście = async (cb, input);
Cout<<"principal function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

String input = String („Funkcja wywołania zwrotnego”);
Principalfn (wejście);
fn ();
String ret = wyjście.Dostawać(); // czeka na zwrot oddzwaniania w razie potrzeby
Cout<powrót 0;

Funkcja Sync () w końcu przechowuje wyjście funkcji wywołania zwrotnego w przyszłym obiekcie. Oczekiwane dane wyjściowe można uzyskać w funkcji Main (), za pomocą funkcji elementu get () obiektu przyszłego.

Wniosek

Funkcja wywołania zwrotnego jest funkcją, która jest argumentem, a nie parametrem, w innej funkcji. Schemat funkcji wywoławczy wymaga głównej funkcji i samej funkcji wywołania zwrotnego. Deklaracja funkcji zwrotnej jest częścią listy parametrów funkcji głównej. Definicja funkcji wywołania wywołania jest wskazana w wywołaniu funkcji funkcji głównej (w main ()). Funkcja wywołania zwrotnego jest faktycznie wywoływana w definicji funkcji głównej.

Schemat funkcji zwrotnej niekoniecznie jest asynchroniczny. Aby mieć pewność, że schemat funkcji wywołania zwrotnego jest asynchroniczny, uczyń główne dane wejściowe do kodu, wejście do funkcji wywołania zwrotnego; Zrób główne dane wyjściowe kodu, wyjście funkcji wywołania zwrotnego; Przechowuj dane wyjściowe funkcji zwrotnej w zmiennej lub strukturze danych. W funkcji Main (), po wywołaniu funkcji głównej, wykonaj inne instrukcje aplikacji. Gdy potrzebne jest wyjście funkcji wywołania zwrotnego, w funkcji main () użyj (odczyt i wyświetl) tam, a następnie.