Функция за обратно повикване в C ++

Callback Function C



Функцията за обратно повикване е функция, която е аргумент, а не параметър, в друга функция. Другата функция може да се нарече главна функция. Така че са включени две функции: главната функция и самата функция за обратно повикване. В списъка с параметри на главната функция, декларацията на функцията за обратно извикване без нейното определение присъства, точно както са налични декларации на обекти без присвояване. Главната функция се извиква с аргументи (в main ()). Един от аргументите в извикването на главната функция е ефективната дефиниция на функцията за обратно извикване. В C ++ този аргумент е препратка към дефиницията на функцията за обратно извикване; това не е действителното определение. Самата функция за обратно извикване всъщност се извиква в дефиницията на главната функция.

Основната функция за обратно извикване в C ++ не гарантира асинхронно поведение в програма. Асинхронното поведение е реалната полза от схемата на функцията за обратно извикване. В асинхронната функция на функцията за обратно извикване резултатът от главната функция трябва да бъде получен за програмата, преди да бъде получен резултатът от функцията за обратно повикване. Това е възможно да се направи в C ++; обаче C ++ има библиотека, наречена future, за да гарантира поведението на асинхронната схема на функцията за обратно извикване.







Тази статия обяснява основната схема на функцията за обратно извикване. Голяма част от него е с чист C ++. Що се отнася до обратното повикване, обяснено е и основното поведение на бъдещата библиотека. Основните познания за C ++ и неговите указатели са необходими за разбирането на тази статия.



Съдържание на статията

Основна схема на функцията за обратно повикване

Схемата на функцията за обратно повикване се нуждае от основна функция и самата функция за обратно повикване. Декларацията на функцията за обратно извикване е част от списъка с параметри на основната функция. Определението на функцията за обратно повикване е посочено в извикването на функцията на основната функция. Функцията за обратно повикване всъщност се извиква в дефиницията на главната функция. Следната програма илюстрира това:



#включва

използвайки пространство на именатачаса;



intmainFn(charгл[],int (*птр)(int))

{

intid1= 1;

intid2= 2;

intобикновено= (*птр)(id2);

цена<<'основна функция:'<<id1<<''<<гл<<''<<обикновено<<'н';

връщанеid1;

}


intcb(intиден)

{

цена<<'функция за обратно повикване'<<'н';

връщанеиден;

}


intглавен()

{

int (*птр)(int) = &cb;

charне[] = 'и';

mainFn(баща, cb);



връщане 0;

}

Изходът е:





функция за обратно повикване

основна функция: 1 и 2

Главната функция се идентифицира с principalFn (). Функцията за обратно повикване се идентифицира с cb (). Функцията за обратно извикване е дефинирана извън главната функция, но всъщност се извиква в основната функция.

Обърнете внимание на декларацията на функцията за обратно извикване като параметър в списъка с параметри на декларацията на основната функция. Декларацията на функцията за обратно извикване е int (*ptr) (int). Обърнете внимание на израза на функцията за обратно извикване, подобно на извикване на функция, в дефиницията на главната функция; всеки аргумент за извикването на функцията за обратно извикване се предава там. Изявлението за това извикване на функция е:



intобикновено= (*птр)(id2);

Където id2 е аргумент. ptr е част от параметъра, показалец, който ще бъде свързан с препратката към функцията за обратно извикване във функцията main ().

Обърнете внимание на израза:

int (*птр)(int) = &cb;

Във функцията main (), която свързва декларацията (без дефиниция) на функцията за обратно повикване с името на дефиницията на същата функция за обратно извикване.

Главната функция се извиква във функцията main (), както следва:

mainFn(баща, cb);

Където cha е низ, а cb е името на функцията за обратно извикване без нито един от нейните аргументи.

Синхронно поведение на функцията за обратно повикване

Помислете за следната програма:

#включва

използвайки пространство на именатачаса;



невалиденmainFn(невалиден (*птр)())

{

цена<<'основна функция'<<'н';

(*птр)();

}


невалиденcb()

{

цена<<'функция за обратно повикване'<<'н';

}


невалиденfn()

{

цена<<'видян'<<'н';

}


intглавен()

{

невалиден (*птр)() = &cb;

mainFn(cb);

fn();



връщане 0;

}

Изходът е:

основна функция

функция за обратно повикване

видяно

Тук има нова функция. Всичко, което прави новата функция, е да показва изхода, видян. В функцията main () се извиква главната функция, след това се извиква новата функция, fn (). Изходът показва, че кодът за главната функция е изпълнен, след това този за функцията за обратно повикване е изпълнен и накрая този за функцията fn () е изпълнен. Това е синхронно (еднонишково) поведение.

Ако това беше асинхронно поведение, когато три кодови сегмента бяха извикани по ред, първият кодов сегмент може да бъде изпълнен, последван от изпълнението на третия кодов сегмент, преди да се изпълни вторият кодов сегмент.

Е, функцията, fn () може да бъде извикана от дефиницията на главната функция, вместо от вътрешната функция main (), както следва:

#включва

използвайки пространство на именатачаса;



невалиденfn()

{

цена<<'видян'<<'н';

}


невалиденmainFn(невалиден (*птр)())

{

цена<<'основна функция'<<'н';

fn();

(*птр)();

}


невалиденcb()

{

цена<<'функция за обратно повикване'<<'н';

}


intглавен()

{

невалиден (*птр)() = &cb;

mainFn(cb);



връщане 0;

}

Изходът е:

основна функция

видяно

функция за обратно повикване

Това е имитация на асинхронно поведение. Това не е асинхронно поведение. Това все още е синхронно поведение.

Също така редът на изпълнение на кодовия сегмент на главната функция и кодовия сегмент на функцията за обратно извикване могат да бъдат разменени в дефиницията на главната функция. Следната програма илюстрира това:

#включва

използвайки пространство на именатачаса;



невалиденmainFn(невалиден (*птр)())

{

(*птр)();

цена<<'основна функция'<<'н';

}


невалиденcb()

{

цена<<'функция за обратно повикване'<<'н';

}


невалиденfn()

{

цена<<'видян'<<'н';

}


intглавен()

{

невалиден (*птр)() = &cb;

mainFn(cb);

fn();



връщане 0;

}

Изходът е сега,

функция за обратно повикване

основна функция

видяно

Това също е имитация на асинхронно поведение. Това не е асинхронно поведение. Това все още е синхронно поведение. Истинското асинхронно поведение може да бъде получено, както е обяснено в следващия раздел или с библиотеката в бъдеще.

Асинхронно поведение с функция за обратно повикване

Псевдокодът за основната асинхронна функция на функцията за обратно извикване е:

тип изход;

тип cb(тип изход)

{

//изявления

}


тип principalFn(тип вход, тип cb(тип изход))

{

//изявления

}

Забележете позициите на входните и изходните данни на различните места на псевдокода. Входът на функцията за обратно повикване е нейният изход. Параметрите на главната функция са входният параметър за общия код и параметърът за функцията за обратно повикване. С тази схема трета функция може да бъде изпълнена (извикана) във функцията main () преди изчисляването на изхода на функцията за обратно повикване (все още във функцията main ()). Следният код илюстрира това:

#включва

използвайки пространство на именатачаса;

char *изход;


невалиденcb(charнавън[])

{

изход=навън;

}



невалиденmainFn(charвход[],невалиден (*птр)(char[петдесет]))

{

(*птр)(вход);

цена<<'основна функция'<<'н';

}


невалиденfn()

{

цена<<'видян'<<'н';

}


intглавен()

{

charвход[] = 'функция за обратно повикване';

невалиден (*птр)(char[]) = &cb;

mainFn(вход, cb);

fn();

цена<<изход<<'н';



връщане 0;

}

Изходът на програмата е:

основна функция

видяно

функция за обратно повикване

В този конкретен код изходната и входната точка е една и съща точка. Резултатът от извикването на третата функция във функцията main () е показан преди резултата от функцията за обратно повикване. Функцията за обратно повикване се изпълнява, завършва и присвоява резултата (стойността) на променливата, изход, което позволява на програмата да продължи без намесата си. Във функцията main () изходът на функцията за обратно извикване се използва (чете и показва), когато е необходимо, което води до асинхронно поведение за цялата схема.

Това е еднопоточният начин за получаване на асинхронно поведение на функцията за обратно извикване с чист C ++.

Основно използване на бъдещата библиотека

Идеята на асинхронната функция на функцията за обратно извикване е, че основната функция се връща преди функцията за обратно повикване. Това беше направено косвено, ефективно, в горния код.

Забележете от горния код, че функцията за обратно повикване приема главния вход за кода и произвежда основния изход за кода. В бъдеще библиотеката на C ++ има функция, наречена sync (). Първият аргумент на тази функция е препратката към функцията за обратно извикване; вторият аргумент е входът за функцията за обратно извикване. Функцията sync () се връща, без да чака изпълнението на функцията за обратно повикване да завърши, но позволява функцията за обратно повикване да завърши. Това осигурява асинхронно поведение. Докато функцията за обратно повикване продължава да се изпълнява, тъй като функцията sync () вече се е върнала, инструкциите под нея продължават да се изпълняват. Това е като идеално асинхронно поведение.

Горната програма е пренаписана по -долу, като се има предвид бъдещата библиотека и нейната функция sync ():

#включва

#включва

#включва

използвайки пространство на именатачаса;

бъдеще<низ>изход;

низ cb(струнен стри)

{

връщанестри;

}



невалиденmainFn(въвеждане на низ)

{

изход=асинхрон(cb, вход);

цена<<'основна функция'<<'н';

}


невалиденfn()

{

цена<<'видян'<<'н';

}


intглавен()

{

въвеждане на низ=низ('функция за обратно повикване');

mainFn(вход);

fn();

низ ret=изход.вземете(); // изчаква връщането да се върне, ако е необходимо

цена<<надясно<<'н';



връщане 0;

}

Функцията sync () най -накрая съхранява изхода на функцията за обратно повикване в бъдещия обект. Очакваният изход може да бъде получен във функцията main (), като се използва функцията член get () на бъдещия обект.

Заключение

Функцията за обратно повикване е функция, която е аргумент, а не параметър, в друга функция. Схемата на функцията за обратно повикване се нуждае от основна функция и самата функция за обратно повикване. Декларацията на функцията за обратно извикване е част от списъка с параметри на основната функция. Определението на функцията за обратно повикване е посочено в извикването на функцията на главната функция (в main ()). Функцията за обратно повикване всъщност се извиква в дефиницията на главната функция.

Схемата на функцията за обратно повикване не е непременно асинхронна. За да сте сигурни, че схемата на функцията за обратно повикване е асинхронна, направете основния вход за кода, входа за функцията за обратно повикване; направете основния изход на кода, изхода на функцията за обратно повикване; съхранява изхода на функцията за обратно повикване в променлива или структура от данни. Във функцията main (), след извикване на функцията principal, изпълнете други изрази на приложението. Когато е необходим изходът на функцията за обратно повикване, във функцията main () го използвайте (четете и показвайте) там и след това.