Tilbagekaldsfunktion i C ++

Callback Function C



En tilbagekaldsfunktion er en funktion, som er et argument, ikke en parameter, i en anden funktion. Den anden funktion kan kaldes hovedfunktionen. Så to funktioner er involveret: hovedfunktionen og selve tilbagekaldsfunktionen. I parameterlisten for hovedfunktionen er erklæringen om tilbagekaldsfunktionen uden dens definition til stede, ligesom objektdeklarationer uden tildeling er til stede. Hovedfunktionen kaldes med argumenter (i main ()). Et af argumenterne i hovedfunktionsopkaldet er den effektive definition af tilbagekaldsfunktionen. I C ++ er dette argument en reference til definitionen af ​​tilbagekaldsfunktionen; det er ikke den egentlige definition. Selve tilbagekaldsfunktionen kaldes faktisk inden for definitionen af ​​hovedfunktionen.

Den grundlæggende tilbagekaldsfunktion i C ++ garanterer ikke asynkron adfærd i et program. Asynkron adfærd er den reelle fordel ved tilbagekaldelsesfunktionsordningen. I det asynkrone tilbagekaldsfunktionsskema skal resultatet af hovedfunktionen indhentes for programmet, før resultatet af tilbagekaldsfunktionen opnås. Det er muligt at gøre dette i C ++; C ++ har imidlertid et bibliotek kaldet fremtid for at garantere opførslen af ​​det asynkrone tilbagekaldsfunktionsskema.







Denne artikel forklarer det grundlæggende callback -funktionsskema. Meget af det er med ren C ++. Hvad tilbagekaldelsen angår, forklares også det fremtidige biblioteks grundlæggende adfærd. Grundlæggende viden om C ++ og dets tips er nødvendig for forståelsen af ​​denne artikel.



Artikelindhold

Grundlæggende tilbagekaldsfunktionsskema

Et opkaldsfunktionsskema har brug for en hovedfunktion og selve tilbagekaldsfunktionen. Erklæringen om tilbagekaldsfunktionen er en del af parameterlisten for hovedfunktionen. Definitionen af ​​tilbagekaldsfunktionen er angivet i funktionsopkaldet til hovedfunktionen. Tilbagekaldsfunktionen kaldes faktisk inden for definitionen af ​​hovedfunktionen. Følgende program illustrerer dette:



#omfatte

ved brug af navnerumtimer;



intmainFn(forkælelsekap[],int (*ptr)(int))

{

intid1= 1;

intid2= 2;

intsom regel= (*ptr)(id2);

koste<<'hovedfunktion:'<<id1<<''<<kap<<''<<som regel<<' n';

Vend tilbageid1;

}


intcb(intiden)

{

koste<<'tilbagekaldsfunktion'<<' n';

Vend tilbageiden;

}


intvigtigste()

{

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

forkælelseingen[] = 'og';

mainFn(far, cb);



Vend tilbage 0;

}

Outputtet er:





tilbagekaldsfunktion

hovedfunktion: 1 og 2

Hovedfunktionen identificeres af principalFn (). Tilbagekaldsfunktionen identificeres med cb (). Tilbagekaldelsesfunktionen defineres uden for hovedfunktionen, men kaldes faktisk inden for hovedfunktionen.

Bemærk erklæringen om tilbagekaldsfunktionen som en parameter i parameterlisten for hovedfunktionserklæringen. Erklæringen om tilbagekaldsfunktionen er int (*ptr) (int). Bemærk tilbagekaldelsesfunktionsudtrykket, ligesom et funktionsopkald, i definitionen af ​​hovedfunktionen; ethvert argument for opkald til funktionsopkald sendes der. Erklæringen for dette funktionsopkald er:



intsom regel= (*ptr)(id2);

Hvor id2 er et argument. ptr er en del af parameteren, en markør, der vil blive knyttet til referencen til tilbagekaldsfunktionen i hovedfunktionen ().

Bemærk udtrykket:

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

I hovedfunktionen (), der forbinder erklæringen (uden definition) af tilbagekaldsfunktionen til navnet på definitionen af ​​den samme tilbagekaldsfunktion.

Hovedfunktionen kaldes i hovedfunktionen () som:

mainFn(far, cb);

Hvor cha er en streng og cb er navnet på tilbagekaldsfunktionen uden nogen af ​​dens argumenter.

Synkron opførsel af tilbagekaldsfunktion

Overvej følgende program:

#omfatte

ved brug af navnerumtimer;



ugyldigmainFn(ugyldig (*ptr)())

{

koste<<'hovedfunktion'<<' n';

(*ptr)();

}


ugyldigcb()

{

koste<<'tilbagekaldsfunktion'<<' n';

}


ugyldigfn()

{

koste<<'set'<<' n';

}


intvigtigste()

{

ugyldig (*ptr)() = &cb;

mainFn(cb);

fn();



Vend tilbage 0;

}

Outputtet er:

hovedfunktion

tilbagekaldsfunktion

set

Der er en ny funktion her. Alt den nye funktion gør, er at vise output, set. I hovedfunktionen () kaldes hovedfunktionen, derefter kaldes den nye funktion, fn (). Outputtet viser, at koden for hovedfunktionen blev udført, derefter blev funktionen for tilbagekaldsfunktionen udført, og endelig blev funktionen for fn () udført. Dette er synkron (enkeltrådet) adfærd.

Hvis det var asynkron adfærd, når tre kodesegmenter kaldes i rækkefølge, kan det første kodesegment eksekveres, i stedet efterfulgt af udførelsen af ​​det tredje kodesegment, før det andet kodesegment udføres.

Nå, funktionen, fn () kan kaldes inde fra definitionen af ​​hovedfunktionen i stedet for inden for hovedfunktionen () som følger:

#omfatte

ved brug af navnerumtimer;



ugyldigfn()

{

koste<<'set'<<' n';

}


ugyldigmainFn(ugyldig (*ptr)())

{

koste<<'hovedfunktion'<<' n';

fn();

(*ptr)();

}


ugyldigcb()

{

koste<<'tilbagekaldsfunktion'<<' n';

}


intvigtigste()

{

ugyldig (*ptr)() = &cb;

mainFn(cb);



Vend tilbage 0;

}

Outputtet er:

hovedfunktion

set

tilbagekaldsfunktion

Dette er en efterligning af asynkron adfærd. Det er ikke asynkron adfærd. Det er stadig synkron adfærd.

Også rækkefølgen af ​​udførelsen af ​​kodesegmentet for hovedfunktionen og kodesegmentet for tilbagekaldsfunktionen kan byttes i definitionen af ​​hovedfunktionen. Følgende program illustrerer dette:

#omfatte

ved brug af navnerumtimer;



ugyldigmainFn(ugyldig (*ptr)())

{

(*ptr)();

koste<<'hovedfunktion'<<' n';

}


ugyldigcb()

{

koste<<'tilbagekaldsfunktion'<<' n';

}


ugyldigfn()

{

koste<<'set'<<' n';

}


intvigtigste()

{

ugyldig (*ptr)() = &cb;

mainFn(cb);

fn();



Vend tilbage 0;

}

Output er nu,

tilbagekaldsfunktion

hovedfunktion

set

Dette er også en efterligning af asynkron adfærd. Det er ikke asynkron adfærd. Det er stadig synkron adfærd. Ægte asynkron adfærd kan opnås som forklaret i det næste afsnit eller med biblioteket, fremtid.

Asynkron adfærd med tilbagekaldsfunktion

Pseudokoden for det grundlæggende asynkrone tilbagekaldsfunktionsskema er:

type output;

type cb(type output)

{

// udsagn

}


type principalFn(type input, type cb(type output))

{

// udsagn

}

Bemærk positionerne for input- og outputdataene på de forskellige steder i pseudokoden. Tilbagekaldsfunktionens input er dens output. Parametrene for hovedfunktionen er inputparameteren for den generelle kode og parameteren for tilbagekaldsfunktionen. Med dette skema kan en tredje funktion udføres (kaldes) i hovedfunktionen (), før output fra tilbagekaldsfunktionen læses (stadig i hovedfunktionen ()). Følgende kode illustrerer dette:

#omfatte

ved brug af navnerumtimer;

forkælelse *produktion;


ugyldigcb(forkælelseud[])

{

produktion=ud;

}



ugyldigmainFn(forkælelseinput[],ugyldig (*ptr)(forkælelse[halvtreds]))

{

(*ptr)(input);

koste<<'hovedfunktion'<<' n';

}


ugyldigfn()

{

koste<<'set'<<' n';

}


intvigtigste()

{

forkælelseinput[] = 'tilbagekaldsfunktion';

ugyldig (*ptr)(forkælelse[]) = &cb;

mainFn(input, cb);

fn();

koste<<produktion<<' n';



Vend tilbage 0;

}

Programoutput er:

hovedfunktion

set

tilbagekaldsfunktion

I denne særlige kode er output- og inputdatoen tilfældigvis det samme nulpunkt. Resultatet af det tredje funktionsopkald i hovedfunktionen () er blevet vist før resultatet af tilbagekaldsfunktionen. Tilbagekaldsfunktionen udført, afsluttet og tildelt sit resultat (værdi) til variablen, output, så programmet kunne fortsætte uden interferens. I hovedfunktionen () blev output fra tilbagekaldsfunktionen brugt (læst og vist), når det var nødvendigt, hvilket førte til asynkron adfærd for hele ordningen.

Dette er den enkeltrådede måde at opnå tilbagekaldsfunktion asynkron adfærd med ren C ++.

Grundlæggende brug af det fremtidige bibliotek

Ideen med det asynkrone tilbagekaldsfunktionsskema er, at hovedfunktionen vender tilbage, før tilbagekaldsfunktionen vender tilbage. Dette blev gjort indirekte, effektivt i ovenstående kode.

Bemærk fra ovenstående kode, at tilbagekaldsfunktionen modtager hovedindgangen til koden og producerer hovedoutput for koden. C ++ - biblioteket, future, har en funktion kaldet sync (). Det første argument til denne funktion er referencefunktionsreferencen; det andet argument er input til tilbagekaldsfunktionen. Synkroniseringsfunktionen () vender tilbage uden at vente på, at tilbagekaldsfunktionen udføres, men tillader genopkaldsfunktionen. Dette giver asynkron adfærd. Mens tilbagekaldsfunktionen fortsætter med at blive udført, da synkroniseringsfunktionen () allerede er vendt tilbage, fortsætter udsagnene herunder. Dette er som ideel asynkron adfærd.

Ovenstående program er blevet omskrevet herunder under hensyntagen til det fremtidige bibliotek og dets synkroniseringsfunktion ():

#omfatte

#omfatte

#omfatte

ved brug af navnerumtimer;

fremtid<snor>produktion;

streng cb(streng stri)

{

Vend tilbagestri;

}



ugyldigmainFn(streng input)

{

produktion=asynk(cb, input);

koste<<'hovedfunktion'<<' n';

}


ugyldigfn()

{

koste<<'set'<<' n';

}


intvigtigste()

{

streng input=snor('tilbagekaldsfunktion');

mainFn(input);

fn();

string ret=produktion.(); // venter på tilbagekald for at vende tilbage om nødvendigt

koste<<ret<<' n';



Vend tilbage 0;

}

Sync () -funktionen gemmer endelig output fra tilbagekaldsfunktionen i det fremtidige objekt. Det forventede output kan opnås i hovedfunktionen () ved hjælp af get () - medlemsfunktionen for det fremtidige objekt.

Konklusion

En tilbagekaldsfunktion er en funktion, som er et argument, ikke en parameter, i en anden funktion. Et opkaldsfunktionsskema har brug for en hovedfunktion og selve tilbagekaldsfunktionen. Erklæringen om tilbagekaldsfunktionen er en del af parameterlisten for hovedfunktionen. Definitionen af ​​tilbagekaldsfunktionen er angivet i funktionsopkaldet til hovedfunktionen (i main ()). Tilbagekaldsfunktionen kaldes faktisk inden for definitionen af ​​hovedfunktionen.

Et tilbagekaldsfunktionsskema er ikke nødvendigvis asynkron. For at være sikker på, at tilbagekaldsfunktionsskemaet er asynkron, skal du indtaste hovedindgangen til koden, input til tilbagekaldsfunktionen; lav hovedoutput af koden, output fra tilbagekaldsfunktionen; gemme output fra tilbagekaldsfunktionen i en variabel eller datastruktur. I hovedfunktionen (), efter at have kaldt til hovedfunktionen, skal du udføre andre udsagn i applikationen. Når output fra tilbagekaldsfunktionen er nødvendig, skal du (læse og vise) det i hovedfunktionen (), der og derefter.