Funcția Callback în C ++

Callback Function C



O funcție de apel invers este o funcție, care este un argument, nu un parametru, într-o altă funcție. Cealaltă funcție poate fi numită funcția principală. Deci sunt implicate două funcții: funcția principală și funcția de apel invers. În lista de parametri a funcției principale, este prezentă declarația funcției callback fără definirea acesteia, la fel cum sunt prezente declarațiile de obiect fără atribuire. Funcția principală este apelată cu argumente (în main ()). Unul dintre argumentele din apelul funcției principale este definiția eficientă a funcției callback. În C ++, acest argument este o referință la definiția funcției de apel invers; nu este definiția propriu-zisă. Funcția callback în sine este de fapt apelată în definiția funcției principale.

Funcția de bază de apel invers în C ++ nu garantează un comportament asincron într-un program. Comportamentul asincron este beneficiul real al schemei de funcții de apel invers. În schema funcției de apel invers asincron, rezultatul funcției principale ar trebui obținut pentru program înainte de a se obține rezultatul funcției de apel invers. Este posibil să faceți acest lucru în C ++; cu toate acestea, C ++ are o bibliotecă numită viitor pentru a garanta comportamentul schemei funcției de apel invers asincron.







Acest articol explică schema de bază a funcției de apelare inversă. O mare parte din aceasta este cu C ++ pur. În ceea ce privește apelul invers, este explicat și comportamentul de bază al viitoarei biblioteci. Cunoașterea de bază a C ++ și a indicatoarelor sale este necesară pentru înțelegerea acestui articol.



Conținutul articolului

Schema de bază a funcției de apelare inversă

O schemă de funcție de apel invers are nevoie de o funcție principală și de funcția de apelare în sine. Declarația funcției de apel invers face parte din lista de parametri a funcției principale. Definiția funcției de apel invers este indicată în apelul de funcție al funcției principale. Funcția de apel invers este de fapt apelată în definiția funcției principale. Următorul program ilustrează acest lucru:



#include

folosind spațiu de numeore;



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

{

intid1= 1;

intid2= 2;

intobișnuit= (*ptr)(id2);

cost<<„funcție principală:”<<id1<<''<<cap<<''<<obișnuit<<' n';

întoarcereid1;

}


intcb(intiden)

{

cost<<„funcție de apel invers”<<' n';

întoarcereiden;

}


intprincipal()

{

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

charNu[] = 'și';

mainFn(tată, cb);



întoarcere 0;

}

Ieșirea este:





funcția de apel invers

funcția principală: 1 și 2

Funcția principală este identificată prin principalFn (). Funcția de apel invers este identificată prin cb (). Funcția de apel invers este definită în afara funcției principale, dar de fapt apelată în cadrul funcției principale.

Rețineți declarația funcției de apel invers ca parametru în lista de parametri a declarației funcției principale. Declarația funcției de apel invers este int (* ptr) (int). Rețineți expresia funcției de apel invers, ca un apel de funcție, în definiția funcției principale; orice argument pentru apelarea funcției de apel invers este transmis acolo. Declarația pentru acest apel funcțional este:



intobișnuit= (*ptr)(id2);

Unde id2 este un argument. ptr face parte din parametru, un pointer, care va fi legat de referința funcției de apel invers în funcția main ().

Rețineți expresia:

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

În funcția main (), care leagă declarația (fără definiție) a funcției de apel invers cu numele definiției aceleiași funcții de apel invers.

Funcția principală se numește, în funcția main (), ca:

mainFn(tată, cb);

Unde cha este un șir și cb este numele funcției de apel invers fără niciun argument al acestuia.

Comportamentul sincron al funcției de apel invers

Luați în considerare următorul program:

#include

folosind spațiu de numeore;



nulmainFn(nul (*ptr)())

{

cost<<„funcție principală”<<' n';

(*ptr)();

}


nulcb()

{

cost<<„funcție de apel invers”<<' n';

}


nulfn()

{

cost<<'văzut'<<' n';

}


intprincipal()

{

nul (*ptr)() = &cb;

mainFn(cb);

fn();



întoarcere 0;

}

Ieșirea este:

funcția principală

funcția de apel invers

văzut

Există o nouă funcție aici. Noua funcție este de a afișa ieșirea, văzută. În funcția main () se numește funcția principală, apoi se numește noua funcție, fn (). Ieșirea arată că a fost executat codul pentru funcția principală, apoi a fost executat cel pentru funcția callback și, în cele din urmă, pentru funcția fn (). Acesta este un comportament sincron (cu un singur fir).

Dacă ar fi un comportament asincron, atunci când trei segmente de cod sunt apelate în ordine, primul segment de cod poate fi executat, urmat în schimb de executarea celui de-al treilea segment de cod, înainte de executarea celui de-al doilea segment de cod.

Ei bine, funcția, fn () poate fi apelată din definiția funcției principale, în loc de din funcția main (), după cum urmează:

#include

folosind spațiu de numeore;



nulfn()

{

cost<<'văzut'<<' n';

}


nulmainFn(nul (*ptr)())

{

cost<<„funcție principală”<<' n';

fn();

(*ptr)();

}


nulcb()

{

cost<<„funcție de apel invers”<<' n';

}


intprincipal()

{

nul (*ptr)() = &cb;

mainFn(cb);



întoarcere 0;

}

Ieșirea este:

funcția principală

văzut

funcția de apel invers

Aceasta este o imitație a comportamentului asincron. Nu este un comportament asincron. Este încă un comportament sincron.

De asemenea, ordinea de execuție a segmentului de cod al funcției principale și a segmentului de cod al funcției de apel invers poate fi schimbată în definiția funcției principale. Următorul program ilustrează acest lucru:

#include

folosind spațiu de numeore;



nulmainFn(nul (*ptr)())

{

(*ptr)();

cost<<„funcție principală”<<' n';

}


nulcb()

{

cost<<„funcție de apel invers”<<' n';

}


nulfn()

{

cost<<'văzut'<<' n';

}


intprincipal()

{

nul (*ptr)() = &cb;

mainFn(cb);

fn();



întoarcere 0;

}

Ieșirea este acum,

funcția de apel invers

funcția principală

văzut

Aceasta este, de asemenea, o imitație a comportamentului asincron. Nu este un comportament asincron. Este încă un comportament sincron. Un adevărat comportament asincron poate fi obținut așa cum se explică în secțiunea următoare sau în bibliotecă, în viitor.

Comportament asincron cu funcție de apel invers

Pseudo-codul pentru schema de bază a funcției de apel invers asincron este:

tip de ieșire;

tastați cb(tip de ieșire)

{

// declarații

}


tip principalFn(tastați intrare, tastați cb(tip de ieșire))

{

// declarații

}

Rețineți pozițiile datelor de intrare și ieșire în diferite locuri ale pseudo-codului. Intrarea funcției de apel invers este ieșirea acesteia. Parametrii funcției principale sunt parametrii de intrare pentru codul general și parametrul pentru funcția de apel invers. Cu această schemă, o a treia funcție poate fi executată (apelată) în funcția main () înainte de citirea ieșirii funcției de apel invers (încă în funcția main ()). Următorul cod ilustrează acest lucru:

#include

folosind spațiu de numeore;

char *ieșire;


nulcb(charafară[])

{

ieșire=afară;

}



nulmainFn(charintrare[],nul (*ptr)(char[cincizeci]))

{

(*ptr)(intrare);

cost<<„funcție principală”<<' n';

}


nulfn()

{

cost<<'văzut'<<' n';

}


intprincipal()

{

charintrare[] = „funcție de apel invers”;

nul (*ptr)(char[]) = &cb;

mainFn(intrare, cb);

fn();

cost<<ieșire<<' n';



întoarcere 0;

}

Ieșirea programului este:

funcția principală

văzut

funcția de apel invers

În acest cod particular, datele de ieșire și de intrare se întâmplă să fie aceleași date. Rezultatul celei de-a treia funcții de apel în funcția main () a fost afișat înainte de rezultatul funcției de apel invers. Funcția de apel invers a executat, a terminat și și-a atribuit rezultatul (valoarea) variabilei, ieșire, permițând programului să continue fără interferența sa. În funcția main (), ieșirea funcției de apel invers a fost utilizată (citită și afișată) când a fost necesară, ducând la un comportament asincron pentru întreaga schemă.

Acesta este modul unic de a obține un comportament asincron al funcției de apelare cu C ++ pur.

Utilizarea de bază a viitoarei Biblioteci

Ideea schemei de funcții de apel invers asincron este că funcția principală revine înainte ca funcția de apel invers să revină. Acest lucru a fost făcut indirect, efectiv, în codul de mai sus.

Rețineți din codul de mai sus că funcția de apel invers primește intrarea principală pentru cod și produce ieșirea principală pentru cod. Biblioteca C ++, viitor, are o funcție numită sync (). Primul argument al acestei funcții este referința funcției de apel invers; al doilea argument este introducerea funcției de apel invers. Funcția sync () revine fără a aștepta finalizarea executării funcției callback, dar permite funcția callback să se finalizeze. Aceasta oferă un comportament asincron. În timp ce funcția de apel invers continuă să se execute, deoarece funcția sync () a revenit deja, instrucțiunile de mai jos continuă să se execute. Acesta este ca un comportament asincron ideal.

Programul de mai sus a fost rescris mai jos, luând în considerare viitoarea bibliotecă și funcția sa de sincronizare ():

#include

#include

#include

folosind spațiu de numeore;

viitor<şir>ieșire;

coarda cb(coarda stri)

{

întoarcerestri;

}



nulmainFn(introducerea șirului)

{

ieșire=asincron(cb, intrare);

cost<<„funcție principală”<<' n';

}


nulfn()

{

cost<<'văzut'<<' n';

}


intprincipal()

{

introducerea șirului=şir(„funcție de apel invers”);

mainFn(intrare);

fn();

șir ret=ieșire.obține(); // așteaptă revenirea apelului, dacă este necesar

cost<<dreapta<<' n';



întoarcere 0;

}

Funcția sync () stochează în cele din urmă ieșirea funcției de apel invers în viitorul obiect. Ieșirea așteptată poate fi obținută în funcția main (), utilizând funcția get () membru a viitorului obiect.

Concluzie

O funcție de apel invers este o funcție, care este un argument, nu un parametru, într-o altă funcție. O schemă de funcție de apel invers are nevoie de o funcție principală și de funcția de apelare în sine. Declarația funcției de apel invers face parte din lista de parametri a funcției principale. Definiția funcției de apel invers este indicată în apelul de funcție al funcției principale (în main ()). Funcția de apel invers este de fapt apelată în definiția funcției principale.

O schemă de funcție de apel invers nu este neapărat asincronă. Pentru a vă asigura că schema funcției de apel invers este asincronă, efectuați intrarea principală în cod, intrarea în funcția de apel invers; efectuați ieșirea principală a codului, ieșirea funcției de apel invers; stocați ieșirea funcției de apel invers într-o structură variabilă sau de date. În funcția main (), după ce ați apelat funcția principală, executați alte instrucțiuni ale aplicației. Când este necesară ieșirea funcției de apel invers, în funcția main (), utilizați-o (citiți și afișați) acolo și apoi.