C ++

Funkce zpětného volání v C ++

Funkce zpětného volání v C ++

Funkce zpětného volání je funkce, která je argumentem, nikoli parametrem, v jiné funkci. Druhou funkci lze nazvat hlavní funkcí. Jedná se tedy o dvě funkce: hlavní funkci a samotnou funkci zpětného volání. V seznamu parametrů hlavní funkce je k dispozici deklarace funkce zpětného volání bez její definice, stejně jako jsou k dispozici deklarace objektů bez přiřazení. Hlavní funkce je volána s argumenty (v main ()). Jedním z argumentů ve volání hlavní funkce je efektivní definice funkce zpětného volání. V C ++ je tento argument odkazem na definici funkce zpětného volání; není to skutečná definice. Samotná funkce zpětného volání je ve skutečnosti volána v rámci definice hlavní funkce.

Základní funkce zpětného volání v C ++ nezaručuje asynchronní chování v programu.  Asynchronní chování je skutečnou výhodou schématu funkce zpětného volání. Ve schématu funkce asynchronního zpětného volání by měl být výsledek hlavní funkce pro program získán před získáním výsledku funkce zpětného volání. Je možné to udělat v C ++; C ++ má však knihovnu nazvanou future, která zaručuje chování schématu funkce asynchronního zpětného volání.

Tento článek vysvětluje základní schéma funkce zpětného volání. Hodně z toho je s čistým C++. Pokud jde o zpětné volání, je vysvětleno také základní chování budoucí knihovny. Pro pochopení tohoto článku jsou nezbytné základní znalosti jazyka C ++ a jeho ukazatelů.

Obsah článku

Základní schéma funkce zpětného volání

Schéma funkce zpětného volání vyžaduje hlavní funkci a samotnou funkci zpětného volání. Deklarace funkce zpětného volání je součástí seznamu parametrů hlavní funkce. Definice funkce zpětného volání je uvedena ve volání funkce hlavní funkce. Funkce zpětného volání je ve skutečnosti volána v rámci definice hlavní funkce. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
int principalFn (char ch [], int (* ptr) (int))

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

int cb (int iden)

cout<<"callback function"<<'\n';
návrat iden;

int main ()

int (* ptr) (int) = &cb;
char cha [] = "a";
principalFn (cha, cb);
návrat 0;

Výstupem je:

funkce zpětného volání
hlavní funkce: 1 a 2

Hlavní funkce je identifikována pomocí principalFn (). Funkce zpětného volání je označena cb (). Funkce zpětného volání je definována mimo hlavní funkci, ale ve skutečnosti je volána v rámci hlavní funkce.

Všimněte si deklarace funkce zpětného volání jako parametru v seznamu parametrů deklarace hlavní funkce. Deklarace funkce zpětného volání je „int (* ptr) (int)“. Všimněte si výrazu funkce zpětného volání, jako je volání funkce, v definici hlavní funkce; je tam předán jakýkoli argument pro volání funkce zpětného volání. Příkaz pro toto volání funkce je:

int idr = (* ptr) (id2);

Kde id2 je argument. ptr je součástí parametru, ukazatele, který bude spojen s odkazem na funkci zpětného volání ve funkci main ().

Všimněte si výrazu:

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

Ve funkci main (), která spojuje deklaraci (bez definice) funkce zpětného volání s názvem definice stejné funkce zpětného volání.

Hlavní funkce se ve funkci main () nazývá jako:

principalFn (cha, cb);

Kde cha je řetězec a cb je název funkce zpětného volání bez jakéhokoli jejího argumentu.

Synchronní chování funkce zpětného volání

Zvažte následující program:

#zahrnout
pomocí jmenného prostoru 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 ();
návrat 0;

Výstupem je:

hlavní funkce
funkce zpětného volání
vidět

Zde je nová funkce. Všechna nová funkce dělá, je zobrazit výstup, „vidět“. Ve funkci main () se volá hlavní funkce, poté se volá nová funkce fn (). Výstup ukazuje, že byl proveden kód pro hlavní funkci, poté byl proveden pro funkci zpětného volání a nakonec byl proveden pro funkci fn (). Toto je synchronní (jednovláknové) chování.

Pokud by šlo o asynchronní chování, když jsou volány tři segmenty kódu v pořadí, může být proveden první segment kódu, následovaný místo toho provedením třetího segmentu kódu před provedením druhého segmentu kódu.

Funkci fn () lze volat z definice hlavní funkce, namísto z funkce main (), a to následovně:

#zahrnout
pomocí jmenného prostoru 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);
návrat 0;

Výstupem je:

hlavní funkce
vidět
funkce zpětného volání

Toto je imitace asynchronního chování. Není to asynchronní chování. Je to stále synchronní chování.

V definici hlavní funkce lze také zaměnit pořadí provádění segmentu kódu hlavní funkce a segmentu kódu funkce zpětného volání. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru 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 ();
návrat 0;

Výstup je nyní,

funkce zpětného volání
hlavní funkce
vidět

Toto je také napodobenina asynchronního chování. Není to asynchronní chování. Je to stále synchronní chování. Pravé asynchronní chování lze získat, jak je vysvětleno v další části nebo s knihovnou, budoucnost.

Asynchronní chování s funkcí zpětného volání

Pseudokód pro základní schéma funkce asynchronního zpětného volání je:

typový výstup;
typ cb (typový výstup)

// příkazy

typ principalFn (typ vstupu, typ cb (typ výstupu))

// příkazy

Poznamenejte si pozice vstupních a výstupních dat na různých místech pseudokódu. Vstupem funkce zpětného volání je její výstup. Parametry hlavní funkce jsou vstupní parametr pro obecný kód a parametr pro funkci zpětného volání. S tímto schématem může být spuštěna (volána) třetí funkce ve funkci main () před načtením výstupu funkce zpětného volání (stále ve funkci main ()). Následující kód to ilustruje:

#zahrnout
pomocí jmenného prostoru std;
char * výstup;
void cb (char out [])

výstup = ven;

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

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

void fn ()

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

int main ()

char input [] = "funkce zpětného volání";
void (* ptr) (char []) = &cb;
principalFn (vstup, cb);
fn ();
cout<návrat 0;

Výstupem programu je:

hlavní funkce
vidět
funkce zpětného volání

V tomto konkrétním kódu je výstupní a vstupní vztažný bod shodný. Výsledek třetího volání funkce ve funkci main () byl zobrazen před výsledkem funkce zpětného volání. Funkce zpětného volání provedená, dokončená a přiřazená jejímu výsledku (hodnotě) proměnné, výstupu, což umožňuje programu pokračovat bez jeho rušení. Ve funkci main () byl použit výstup funkce zpětného volání (čten a zobrazen), když to bylo potřeba, což vedlo k asynchronnímu chování pro celé schéma.

Toto je jednovláknový způsob, jak získat asynchronní chování funkce zpětného volání s čistým C++.

Základní využití budoucí knihovny

Myšlenka schématu funkce asynchronního zpětného volání je, že se hlavní funkce vrátí před návratovou funkcí zpětného volání. To bylo provedeno nepřímo, efektivně, ve výše uvedeném kódu.

Z výše uvedeného kódu si povšimněte, že funkce zpětného volání přijímá hlavní vstup pro kód a vytváří hlavní výstup pro kód. Knihovna C ++, budoucnost, má funkci nazvanou sync (). Prvním argumentem této funkce je odkaz na funkci zpětného volání; druhým argumentem je vstup do funkce zpětného volání. Funkce sync () se vrací bez čekání na dokončení provedení funkce zpětného volání, ale umožňuje dokončení funkce zpětného volání. To poskytuje asynchronní chování. Zatímco funkce zpětného volání pokračuje v provádění, protože funkce sync () se již vrátila, příkazy pod ní se nadále spouštějí. To je jako ideální asynchronní chování.

Výše uvedený program byl přepsán níže s ohledem na budoucí knihovnu a její funkci synchronizace ():

#zahrnout
#zahrnout
#zahrnout
pomocí jmenného prostoru std;
budoucnost výstup;
string cb (string stri)

návrat stri;

void principalFn (vstup řetězce)

výstup = asynchronní (cb, vstup);
cout<<"principal function"<<'\n';

void fn ()

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

int main ()

string input = string ("callback function");
principalFn (vstup);
fn ();
řetězec ret = výstup.dostat(); // čeká na zpětné volání v případě potřeby
cout<návrat 0;

Funkce sync () konečně uloží výstup funkce zpětného volání do budoucího objektu. Očekávaný výstup lze získat ve funkci main () pomocí členské funkce get () budoucího objektu.

Závěr

Funkce zpětného volání je funkce, která je argumentem, nikoli parametrem, v jiné funkci. Schéma funkce zpětného volání vyžaduje hlavní funkci a samotnou funkci zpětného volání. Deklarace funkce zpětného volání je součástí seznamu parametrů hlavní funkce. Definice funkce zpětného volání je uvedena ve volání funkce hlavní funkce (v main ()). Funkce zpětného volání je ve skutečnosti volána v rámci definice hlavní funkce.

Schéma funkce zpětného volání nemusí být nutně asynchronní. Chcete-li mít jistotu, že schéma funkce zpětného volání je asynchronní, proveďte hlavní vstup do kódu, vstup do funkce zpětného volání; provést hlavní výstup kódu, výstup funkce zpětného volání; uložit výstup funkce zpětného volání do proměnné nebo datové struktury. Ve funkci main () po volání hlavní funkce proveďte další příkazy aplikace. Když je potřeba výstup funkce zpětného volání, ve funkci main () ji použijte (čtěte a zobrazte) tam a poté.

Hry Výukový program Battle for Wesnoth
Výukový program Battle for Wesnoth
The Battle for Wesnoth je jednou z nejpopulárnějších strategických her s otevřeným zdrojovým kódem, které si v tuto chvíli můžete zahrát. Tato hra se ...
Hry 0 A.D. Tutorial
0 A.D. Tutorial
Z mnoha strategických her venku je 0 A.D. dokáže vyniknout jako komplexní titul a velmi hluboká, taktická hra, přestože je otevřeným zdrojem. Vývoj hr...
Hry Výukový program Unity3D
Výukový program Unity3D
Úvod do Unity 3D Unity 3D je výkonný engine pro vývoj her. Jedná se o multiplatformní platformu, která vám umožňuje vytvářet hry pro mobilní zařízení,...