Återuppringningsfunktion i C ++

Callback Function C



En återuppringningsfunktion är en funktion, som är ett argument, inte en parameter, i en annan funktion. Den andra funktionen kan kallas huvudfunktionen. Så två funktioner är inblandade: huvudfunktionen och själva återuppringningsfunktionen. I parameterlistan för huvudfunktionen finns deklarationen för återuppringningsfunktionen utan dess definition, precis som objektdeklarationer utan tilldelning finns. Huvudfunktionen kallas med argument (i main ()). Ett av argumenten i huvudfunktionsanropet är den effektiva definitionen av återuppringningsfunktionen. I C ++ är detta argument en referens till definitionen av återuppringningsfunktionen; det är inte den egentliga definitionen. Själva återuppringningsfunktionen kallas faktiskt inom definitionen av huvudfunktionen.

Den grundläggande återuppringningsfunktionen i C ++ garanterar inte asynkront beteende i ett program. Asynkront beteende är den verkliga fördelen med återuppringningsfunktionsschemat. I det asynkrona återuppringningsfunktionsschemat bör resultatet av huvudfunktionen erhållas för programmet innan resultatet av återuppringningsfunktionen erhålls. Det är möjligt att göra detta i C ++; C ++ har dock ett bibliotek som kallas framtida för att garantera beteendet hos det asynkrona återuppringningsfunktionsschemat.







Den här artikeln förklarar det grundläggande återuppringningsfunktionsschemat. Mycket av det är med ren C ++. När det gäller återuppringning förklaras också det framtida bibliotekets grundbeteende. Grundläggande kunskaper om C ++ och dess tips är nödvändiga för förståelsen av denna artikel.



Artikelinnehåll

Grundläggande återuppringningsfunktionsschema

Ett återuppringningsfunktionsschema behöver en huvudfunktion och själva återuppringningsfunktionen. Deklarationen för återuppringningsfunktionen är en del av parameterlistan för huvudfunktionen. Definitionen av återuppringningsfunktionen anges i funktionsanropet för huvudfunktionen. Återuppringningsfunktionen kallas faktiskt inom definitionen av huvudfunktionen. Följande program illustrerar detta:



#omfatta

använder sig av namnrymdtimmar;



intmainFn(rödingkap[],int (*ptr)(int))

{

intid1= 1;

intid2= 2;

intvanligtvis= (*ptr)(id2);

kosta<<'huvudfunktion:'<<id1<<''<<kap<<''<<vanligtvis<<' n';

lämna tillbakaid1;

}


intcb(intiden)

{

kosta<<'återuppringningsfunktion'<<' n';

lämna tillbakaiden;

}


inthuvud()

{

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

rödingNej[] = 'och';

mainFn(far, cb);



lämna tillbaka 0;

}

Utgången är:





återuppringningsfunktion

huvudfunktion: 1 och 2

Huvudfunktionen identifieras av principalFn (). Återuppringningsfunktionen identifieras med cb (). Återuppringningsfunktionen definieras utanför huvudfunktionen men kallas faktiskt inom huvudfunktionen.

Notera deklarationen för återuppringningsfunktionen som en parameter i parameterlistan för huvudfunktionsdeklarationen. Deklarationen för återuppringningsfunktionen är int (*ptr) (int). Lägg märke till återuppringningsfunktionsuttrycket, som ett funktionsanrop, i definitionen av huvudfunktionen; alla argument för återuppringningsfunktionssamtalet skickas dit. Påståendet för detta funktionsanrop är:



intvanligtvis= (*ptr)(id2);

Där id2 är ett argument. ptr är en del av parametern, en pekare, som kommer att länkas till referensen för återuppringningsfunktionen i huvudfunktionen ().

Notera uttrycket:

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

I huvudfunktionen (), som länkar deklarationen (utan definition) för återuppringningsfunktionen till namnet på definitionen av samma återuppringningsfunktion.

Huvudfunktionen kallas i huvudfunktionen () som:

mainFn(far, cb);

Där cha är en sträng och cb är namnet på återuppringningsfunktionen utan något av dess argument.

Synkron beteende för återuppringningsfunktionen

Tänk på följande program:

#omfatta

använder sig av namnrymdtimmar;



tomhetmainFn(tomhet (*ptr)())

{

kosta<<'huvudfunktion'<<' n';

(*ptr)();

}


tomhetcb()

{

kosta<<'återuppringningsfunktion'<<' n';

}


tomhetfn()

{

kosta<<'sett'<<' n';

}


inthuvud()

{

tomhet (*ptr)() = &cb;

mainFn(cb);

fn();



lämna tillbaka 0;

}

Utgången är:

huvudfunktion

återuppringningsfunktion

sett

Det finns en ny funktion här. Allt den nya funktionen gör, är att visa utgången, sett. I huvudfunktionen () kallas huvudfunktionen, sedan kallas den nya funktionen, fn (). Utdata visar att koden för huvudfunktionen exekverades, sedan utfördes den för återuppringningsfunktionen och slutligen utfördes den för funktionen fn (). Detta är synkront (enkeltrådat) beteende.

Om det var asynkront beteende, när tre kodsegment anropas i ordning, kan det första kodsegmentet köras, följt av körningen av det tredje kodsegmentet, innan det andra kodsegmentet körs.

Tja, funktionen, fn () kan kallas inifrån definitionen av huvudfunktionen, i stället för inifrån huvudfunktionen (), enligt följande:

#omfatta

använder sig av namnrymdtimmar;



tomhetfn()

{

kosta<<'sett'<<' n';

}


tomhetmainFn(tomhet (*ptr)())

{

kosta<<'huvudfunktion'<<' n';

fn();

(*ptr)();

}


tomhetcb()

{

kosta<<'återuppringningsfunktion'<<' n';

}


inthuvud()

{

tomhet (*ptr)() = &cb;

mainFn(cb);



lämna tillbaka 0;

}

Utgången är:

huvudfunktion

sett

återuppringningsfunktion

Detta är en imitation av asynkront beteende. Det är inte asynkront beteende. Det är fortfarande synkront beteende.

Även ordningsföljden för kodsegmentet för huvudfunktionen och kodsegmentet för återuppringningsfunktionen kan bytas ut i definitionen av huvudfunktionen. Följande program illustrerar detta:

#omfatta

använder sig av namnrymdtimmar;



tomhetmainFn(tomhet (*ptr)())

{

(*ptr)();

kosta<<'huvudfunktion'<<' n';

}


tomhetcb()

{

kosta<<'återuppringningsfunktion'<<' n';

}


tomhetfn()

{

kosta<<'sett'<<' n';

}


inthuvud()

{

tomhet (*ptr)() = &cb;

mainFn(cb);

fn();



lämna tillbaka 0;

}

Utgången är nu,

återuppringningsfunktion

huvudfunktion

sett

Detta är också en imitation av asynkront beteende. Det är inte asynkront beteende. Det är fortfarande synkront beteende. Äkta asynkront beteende kan erhållas enligt förklaringen i nästa avsnitt eller med biblioteket, framtiden.

Asynkront beteende med återuppringningsfunktion

Pseudokoden för det grundläggande asynkrona återuppringningsfunktionsschemat är:

typ utgång;

typ cb(typ utgång)

{

// uttalanden

}


typ principalFn(typ input, typ cb(typ utgång))

{

// uttalanden

}

Notera positionerna för in- och utdata på pseudokodens olika platser. Ingången till återuppringningsfunktionen är dess utgång. Parametrarna för huvudfunktionen är ingångsparametern för den allmänna koden och parametern för återuppringningsfunktionen. Med detta schema kan en tredje funktion exekveras (kallas) i huvudfunktionen () innan utgången från återuppringningsfunktionen läses (fortfarande i huvudfunktionen ()). Följande kod illustrerar detta:

#omfatta

använder sig av namnrymdtimmar;

röding *produktion;


tomhetcb(rödingut[])

{

produktion=ut;

}



tomhetmainFn(rödinginmatning[],tomhet (*ptr)(röding[femtio]))

{

(*ptr)(inmatning);

kosta<<'huvudfunktion'<<' n';

}


tomhetfn()

{

kosta<<'sett'<<' n';

}


inthuvud()

{

rödinginmatning[] = 'återuppringningsfunktion';

tomhet (*ptr)(röding[]) = &cb;

mainFn(ingång, cb);

fn();

kosta<<produktion<<' n';



lämna tillbaka 0;

}

Programutmatningen är:

huvudfunktion

sett

återuppringningsfunktion

I denna specifika kod råkar utgångs- och ingångsdata vara samma datum. Resultatet av det tredje funktionsanropet i huvudfunktionen () har visats före resultatet av återuppringningsfunktionen. Återuppringningsfunktionen exekverades, slutfördes och tilldelade dess resultat (värde) variabeln, utgång, så att programmet kunde fortsätta utan störningar. I huvudfunktionen () användes utgången från återuppringningsfunktionen (läs och visas) när den behövdes, vilket ledde till asynkront beteende för hela schemat.

Detta är det enda trådade sättet att få asynkron beteende för återuppringningsfunktion med ren C ++.

Grundläggande användning av det framtida biblioteket

Tanken med det asynkrona återuppringningsfunktionsschemat är att huvudfunktionen återkommer innan återuppringningsfunktionen återkommer. Detta gjordes indirekt, effektivt, i ovanstående kod.

Notera från ovanstående kod att återuppringningsfunktionen tar emot huvudingången för koden och producerar huvudutmatningen för koden. C ++ - biblioteket, framtiden, har en funktion som kallas sync (). Det första argumentet till denna funktion är återuppringningsfunktionsreferensen; det andra argumentet är ingången till återuppringningsfunktionen. Sync () -funktionen återgår utan att vänta på att återuppringningsfunktionen ska slutföras men tillåter återuppringningsfunktionen. Detta ger asynkront beteende. Medan återuppringningsfunktionen fortsätter att köra, eftersom synkroniseringsfunktionen () redan har återvänt, fortsätter uttalandena nedanför att köra. Detta är som idealiskt asynkront beteende.

Ovanstående program har skrivits om nedan, med beaktande av det framtida biblioteket och dess synkroniseringsfunktion ():

#omfatta

#omfatta

#omfatta

använder sig av namnrymdtimmar;

framtida<sträng>produktion;

sträng cb(sträng stri)

{

lämna tillbakastri;

}



tomhetmainFn(stränginmatning)

{

produktion=asynk(cb, ingång);

kosta<<'huvudfunktion'<<' n';

}


tomhetfn()

{

kosta<<'sett'<<' n';

}


inthuvud()

{

stränginmatning=sträng('återuppringningsfunktion');

mainFn(inmatning);

fn();

sträng ret=produktion.skaffa sig(); // väntar på att återuppringning ska återkomma om det behövs

kosta<<höger<<' n';



lämna tillbaka 0;

}

Funktionen sync () lagrar slutligen utgången från återuppringningsfunktionen i det framtida objektet. Den förväntade utmatningen kan erhållas i huvudfunktionen () med hjälp av get () -medelfunktionen för det framtida objektet.

Slutsats

En återuppringningsfunktion är en funktion, som är ett argument, inte en parameter, i en annan funktion. Ett återuppringningsfunktionsschema behöver en huvudfunktion och själva återuppringningsfunktionen. Deklarationen för återuppringningsfunktionen är en del av parameterlistan för huvudfunktionen. Definitionen av återuppringningsfunktionen anges i funktionsanropet för huvudfunktionen (i huvud ()). Återuppringningsfunktionen kallas faktiskt inom definitionen av huvudfunktionen.

Ett återuppringningsfunktionsschema är inte nödvändigtvis asynkron. För att vara säker på att återuppringningsfunktionsschemat är asynkron, gör huvudingången till koden, ingången till återuppringningsfunktionen; göra huvudutmatningen av koden, utgången från återuppringningsfunktionen; lagra utgången från återuppringningsfunktionen i en variabel eller datastruktur. I huvudfunktionen (), efter att ha ringt till huvudfunktionen, kör andra uttalanden i applikationen. När utmatningen från återuppringningsfunktionen behövs, i huvudfunktionen (), använd (läs och visa) den där och då.