C++

Funkcja wywołania zwrotnego w C++

Funkcja wywołania zwrotnego w C++

Funkcja wywołania zwrotnego to funkcja będąca argumentem, a nie parametrem w innej funkcji. Drugą funkcję można nazwać funkcją główną. W grę wchodzą więc dwie funkcje: główna funkcja i sama funkcja wywołania zwrotnego. Na liście parametrów funkcji principal znajduje się deklaracja funkcji zwrotnej bez jej definicji, podobnie jak deklaracje obiektów bez przypisania. Główna funkcja jest wywoływana z argumentami (w main()). Jednym z argumentów w wywołaniu funkcji głównej jest efektywna definicja funkcji zwrotnej. W C++ ten argument jest odwołaniem do definicji funkcji zwrotnej; to nie jest faktyczna definicja. Sama funkcja zwrotna jest w rzeczywistości wywoływana w ramach definicji funkcji głównej.

Podstawowa funkcja zwrotna w C++ nie gwarantuje asynchronicznego zachowania w programie in.  Zachowanie asynchroniczne to prawdziwa zaleta schematu funkcji wywołania zwrotnego. W schemacie funkcji wywołania zwrotnego asynchronicznego wynik funkcji głównej powinien zostać uzyskany dla programu przed uzyskaniem wyniku funkcji wywołania zwrotnego. Można to zrobić w C++; jednak C++ ma bibliotekę o nazwie future, która gwarantuje zachowanie schematu asynchronicznej funkcji zwrotnejback.

W tym artykule wyjaśniono podstawowy schemat funkcji wywołania zwrotnego. Dużo jest z czystym C++. Jeśli chodzi o callback, wyjaśniono również podstawowe zachowanie przyszłej biblioteki. Do zrozumienia tego artykułu niezbędna jest podstawowa znajomość C++ i jego wskaźnikówers.

Treść artykułu

Podstawowy schemat funkcji oddzwaniania

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

#zawierać
przy użyciu standardowej przestrzeni nazw;
int principalFn(char ch[], int (*ptr)(int))

int id1 = 1;
int id2 = 2;
int idr = (*ptr)(id2);
Cout<<"principal function: "<zwróć id1;

int cb(identyfikator int)

Cout<<"callback function"<<'\n';
identyfikator powrotu;

int main()

int (*ptr)(int) = &cb;
char cha[] = "i";
głównyFn(cha, cb);
zwróć 0;

Dane wyjściowe to:

funkcja oddzwaniania
główna funkcja: 1 i 2

Główna funkcja jest identyfikowana przez principalFn(). Funkcja zwrotna jest identyfikowana przez cb(). Funkcja wywołania zwrotnego jest zdefiniowana poza funkcją principal, ale w rzeczywistości jest wywoływana w funkcji principal.

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

int idr = (*ptr)(id2);

Gdzie id2 jest argumentem. ptr jest częścią parametru, wskaźnikiem, który będzie połączony z referencją funkcji zwrotnej w funkcji main().

Zwróć uwagę na wyrażenie:

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

W funkcji main(), która łączy deklarację (bez definicji) funkcji zwrotnej z nazwą definicji tej samej funkcji zwrotnej.

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

głównyFn(cha, cb);

Gdzie cha jest napisem, a cb jest nazwą funkcji zwrotnej bez żadnego jej argumentu.

Synchroniczne zachowanie funkcji wywołania zwrotnego

Rozważ następujący program:

#zawierać
przy użyciu standardowej przestrzeni nazw;
nieważny głównyFn(nieważny (*ptr)())

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

nieważne cb()

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

nieważne fn()

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

int main()

nieważne (*ptr)() = &cb;
głównyFn(cb);
fn();
zwróć 0;

Dane wyjściowe to:

główna funkcja
funkcja oddzwaniania
widziany

Jest tu nowa funkcja. Wszystko, co robi nowa funkcja, to wyświetlanie danych wyjściowych „widzianych”. W funkcji main() wywoływana jest funkcja główna, a następnie wywoływana jest nowa funkcja fn(). Wynik pokazuje, że kod dla funkcji głównej został wykonany, następnie dla funkcji zwrotnej, a na końcu dla funkcji fn(). Jest to zachowanie synchroniczne (jednowątkowe).

Gdyby było to zachowanie asynchroniczne, gdy trzy segmenty kodu są wywoływane w kolejności, pierwszy segment kodu może zostać wykonany, po czym zamiast tego wykonać trzeci segment kodu, przed wykonaniem drugiego segmentu kodu.

Cóż, funkcję fn() można wywołać z definicji funkcji głównej, zamiast z funkcji main(), w następujący sposób:

#zawierać
przy użyciu standardowej przestrzeni nazw;
nieważne fn()

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

nieważny głównyFn(nieważny (*ptr)())

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

nieważne cb()

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

int main()

nieważne (*ptr)() = &cb;
głównyFn(cb);
zwróć 0;

Dane wyjściowe to:

główna funkcja
widziany
funkcja oddzwaniania

Jest to imitacja zachowania asynchronicznego. To nie jest zachowanie asynchroniczne. To nadal jest zachowanie synchroniczne.

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

#zawierać
przy użyciu standardowej przestrzeni nazw;
 
nieważny głównyFn(nieważny (*ptr)())

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

nieważne cb()

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

nieważne fn()

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

int main()

nieważne (*ptr)() = &cb;
głównyFn(cb);
fn();
zwróć 0;

Wyjście jest teraz,

funkcja oddzwaniania
główna funkcja
widziany

Jest to również imitacja zachowania asynchronicznego. To nie jest zachowanie asynchroniczne. To nadal jest zachowanie synchroniczne. Prawdziwe zachowanie asynchroniczne można uzyskać, jak wyjaśniono w następnej sekcji lub za pomocą biblioteki, future.

Zachowanie asynchroniczne z funkcją wywołania zwrotnego

Pseudokod podstawowego schematu funkcji asynchronicznego wywołania zwrotnego to:

typ wyjścia;
wpisz cb (typ wyjścia)

//sprawozdania

wpisz principalFn(typ wejścia, wpisz cb(typ wyjścia))

//sprawozdania

Zwróć uwagę na pozycje danych wejściowych i wyjściowych w różnych miejscach pseudokodu. Wejście funkcji zwrotnej jest jej wyjściem. Parametry funkcji głównej są parametrem wejściowym kodu ogólnego i parametrem funkcji zwrotnej. W tym schemacie można wykonać (wywołać) trzecią funkcję w funkcji main() przed odczytaniem wyjścia funkcji zwrotnej (nadal w funkcji main()). Poniższy kod ilustruje to:

#zawierać
przy użyciu standardowej przestrzeni nazw;
znak *wyjście;
void cb(char out[])

wyjście = wyjście;

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

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

nieważne fn()

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

int main()

char input[] = "funkcja wywołania zwrotnego";
void (*ptr)(char[]) = &cb;
głównyFn(wejście, cb);
fn();
Cout<zwróć 0;

Wyjście programu to:

główna funkcja
widziany
funkcja oddzwaniania

W tym konkretnym kodzie dane wyjściowe i wejściowe są tym samym punktem odniesienia. Wynik trzeciego wywołania funkcji w funkcji main() został wyświetlony przed wynikiem funkcji zwrotnej. Funkcja wywołania zwrotnego wykonała, zakończyła i przypisała swój wynik (wartość) do zmiennej, wyjście, umożliwiając kontynuowanie programu bez jego ingerencji. W funkcji main() wyjście funkcji zwrotnej było używane (odczytywane i wyświetlane), gdy było to potrzebne, co prowadziło do asynchronicznego zachowania całego schematu.

Jest to jednowątkowy sposób na uzyskanie asynchronicznego zachowania funkcji wywołania zwrotnego z czystym C++.

Podstawowe użytkowanie przyszłej Biblioteki

Idea schematu asynchronicznej funkcji wywołania zwrotnego polega na tym, że główna funkcja zwraca się przed powrotem z funkcji wywołania zwrotnego. Zostało to zrobione pośrednio, skutecznie, w powyższym kodzie.

Zauważ z powyższego kodu, że funkcja callback otrzymuje główne wejście dla kodu i generuje główne wyjście dla kodu for. Przyszłość biblioteki C++ ma funkcję o nazwie sync(). Pierwszym argumentem tej funkcji jest odwołanie do funkcji zwrotnej; drugi argument to dane wejściowe funkcji zwrotnej. Funkcja sync() powraca bez czekania na zakończenie wykonania funkcji zwrotnej, ale umożliwia zakończenie funkcji zwrotnej. Zapewnia to zachowanie asynchroniczne. Podczas gdy funkcja wywołania zwrotnego nadal wykonuje się, ponieważ funkcja sync() już zwróciła, poniższe instrukcje są nadal wykonywane. To jest jak idealne zachowanie asynchroniczne.

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

#zawierać
#zawierać
#zawierać
przy użyciu standardowej przestrzeni nazw;
przyszłość wynik;
string cb(string string)

powrót stri;

void principalFn(ciąg znaków wejściowych)

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

nieważne fn()

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

int main()

string input = string("funkcja wywołania zwrotnego");
głównyFn(wejście);
fn();
ciąg ret = wyjście.otrzymać(); //czeka na powrót wywołania zwrotnego, jeśli to konieczne
Cout<zwróć 0;

Funkcja sync() ostatecznie przechowuje dane wyjściowe funkcji zwrotnej w przyszłym obiekcie. Oczekiwany wynik można uzyskać w funkcji main(), używając funkcji składowej get() przyszłego obiektu.

Wniosek

Funkcja wywołania zwrotnego to funkcja będąca argumentem, a nie parametrem w innej funkcji. Schemat funkcji zwrotnej wymaga głównej funkcji, a sama funkcja zwrotna. Deklaracja funkcji zwrotnej jest częścią listy parametrów funkcji głównej. Definicja funkcji zwrotnej jest wskazana w wywołaniu funkcji głównej funkcji (w main()). Funkcja wywołania zwrotnego jest faktycznie wywoływana w ramach definicji funkcji głównej.

Schemat funkcji zwrotnej niekoniecznie jest asynchroniczny. Aby mieć pewność, że schemat funkcji wywołania zwrotnego jest asynchroniczny, wprowadź główne dane wejściowe kodu, a dane wejściowe funkcji wywołania zwrotnego; zrobić główne wyjście kodu, wyjście funkcji zwrotnej; przechowywać 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 zwrotnej, w funkcji main() użyj (odczytaj i wyświetl) je tam, a potem.

Mouse left-click button not working on Windows 10
If you are using a dedicated mouse with your laptop, or desktop computer but the mouse left-click button is not working on Windows 10/8/7 for some rea...
Cursor jumps or moves randomly while typing in Windows 10
If you find that your mouse cursor jumps or moves on its own, automatically, randomly while typing in Windows laptop or computer, then some of these s...
How to reverse Mouse and Touchpads scrolling direction in Windows 10
Mouse and Touchpads not only make computing easy but more efficient and less time-consuming. We cannot imagine a life without these devices, but still...