C ++ atgalinio ryšio funkcijos

C + +, kada ir kaip naudojate atgalinio ryšio funkciją?

EDIT:
Norėčiau matyti paprastą atgalinio ryšio funkcijos rašymo pavyzdį.

239
19 февр. nustatykite cpx 19 vasario mėn 2010-02-19 20:16 '10, 20:16, 2010-02-19 20:16
@ 9 atsakymai

Pastaba Dauguma atsakymų yra susiję su funkcijų rodikliais, kurie yra viena iš galimybių pasiekti atgalinio ryšio logiką C + +, bet šiandien, manau, nėra palankiausia.

Kas yra skambučiai (?) Ir kodėl juos naudoti (!)

Atgalinis ryšys yra skambinamas (žr. Toliau) metodas, priimtas pagal klasę arba funkciją, kuri naudojama nustatyti dabartinę logiką, priklausomai nuo šio atgalinio ryšio.

Viena iš priežasčių, kodėl naudojatės „callbacks“, yra parašyti universalų kodą, kuris nepriklauso nuo vadinamosios funkcijos logikos ir gali būti pakartotinai naudojamas su skirtingais atsiliepimais.

Daugelis standartinės algoritmo bibliotekos <algorithm> funkcijų naudoja „callbacks“. Pvz., for_each algoritmas kiekvienam elemento iteratorių elementui taiko vienodą atšaukimą:

 template<class InputIt, class UnaryFunction> UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f) { for (; first != last; ++first) { f(*first); } return f; } 

kuris gali būti naudojamas pirmiausia padidinti ir spausdinti vektorių, perduodant atitinkamus skambučius, pavyzdžiui:

 std::vector<double> v{ 1.0, 2.2, 4.0, 5.5, 7.2 }; double r = 4.0; std::for_each(v.begin(), v.end(), [  v) { v += r; }); std::for_each(v.begin(), v.end(), [](double v) { std::cout << v << " "; }); 

kuri spausdina

 5 6.2 8 9.5 11.2 

Kitas „callbacks“ naudojimas yra informuoti skambinančius asmenis apie tam tikrus įvykius, kurie suteikia tam tikrą statinio / kompiliavimo laiko lankstumą.

Asmeniškai naudoju vietinę optimizavimo biblioteką, kurioje naudojami du skirtingi atsiliepimai:

  • Pirmasis atšaukimas vadinamas, jei reikalinga funkcijų vertė ir gradientas, pagrįstas įvesties verčių vektoriu (loginis atšaukimas: funkcijos vertės nustatymas / gradiento gavimas).
  • Antrasis atgalinis ryšys vadinamas vieną kartą kiekvienam algoritmo etapui ir gauna tam tikrą informaciją apie algoritmo konvergenciją (pranešimo atšaukimas).

Taigi bibliotekos kūrėjas neatsako už tai, kas atsitinka su informacija, kuri programuotojui teikiama per atgalinio ryšio pranešimą, ir jam nereikia nerimauti, kaip faktiškai nustatyti funkcijų vertes, nes jas teikia loginis atšaukimas. Teisingas šių užduočių sprendimas yra bibliotekos naudotojo užduotis, o biblioteka tampa plati ir bendresnė.

Be to, atšaukimai gali apimti dinaminį elgesį veikimo metu.

Įsivaizduokite tam tikrą žaidimų variklio klasę, kuri turi funkciją, kuri veikia kiekvieną kartą, kai vartotojas paspaudžia klaviatūros mygtuką, ir funkcijų, valdančių jūsų žaidimų elgesį, rinkinį. Naudodami „callbacks“, galite (pakartotinai) nuspręsti, kokių veiksmų bus imtasi.

 void player_jump(); void player_crouch(); class game_core { std::array<void(*)(), total_num_keys> actions; // void key_pressed(unsigned key_id) { if(actions[key_id]) actions[key_id](); } // update keybind from menu void update_keybind(unsigned key_id, void(*new_action)()) { actions[key_id] = new_action; } }; 

Čia funkcija „ key_pressed naudoja actions , išsaugotus actions norint gauti norimą elgesį, kai paspaudžiamas tam tikras klavišas. Jei žaidėjas nusprendžia pakeisti šuolio mygtuką, variklis gali sukelti

 game_core_instance.update_keybind(newly_selected_key, > 

ir, pakeisdami šį mygtuką kitą kartą žaidimo metu, pakeiskite skambučių elgesį į key_pressed (kuris vadina player_jump ).

Kas vadinama C ++ (11)?

Žr. „ C ++ Concepts“: skambinant į oficialų aprašymą.

Atgalinio atšaukimo funkcija gali būti įgyvendinta keliais būdais C ++ (11), nes gali būti vadinami keli skirtingi dalykai:

  • Funkcijų nuorodos (įskaitant nario funkcijų rodykles)
  • objektai std::function
  • Lambda išraiškos
  • Išraiška privaloma
  • Funkcijų objektai (klasės su perkrautomis funkcijomis, skambučių operator() )

* Pastaba: taip pat gali būti vadinamas rodyklė į duomenų elementus, tačiau funkcija visai neskambinama.

Keletas svarbių būdų, kaip išsamiai parašyti skambučius.

  • X.1 „Rašymas“ šiame įraše reiškia atgalinio ryšio tipo paskelbimo ir pavadinimo sintaksę.
  • X.2 Skambinimas atgaliniu ryšiu reiškia sintaksę šiems objektams skambinti.
  • X.3 „Naudojimas“ atgalinis ryšys - tai sintaksė, skirta argumentams perduoti funkcijai naudojant atgalinio ryšio funkciją.

Pastaba Pradedant nuo C ++ 17, f(...) tipo skambutis gali būti parašytas kaip std::invoke(f,...) kuris taip pat apdoroja rodyklę į nario registrą.

1. Funkciniai rodikliai

Funkcijų rodyklė yra „paprasčiausias“ (visuotinumo, skaitomumo, galbūt blogiausio) tipo, kuris gali turėti atgalinį ryšį.

Tegul yra paprasta funkcija:

 int foo (int x) { return 2+x; } 

1.1 Rašymo funkcijos indeksas / tipo žymėjimas

Nurodomas funkcijos rodyklės tipas

 return_type (*)(parameter_type_1, parameter_type_2, parameter_type_3) // ie a pointer to foo has the type: int (*)(int) 

kur atrodys rodyklės tipas prie pavadintos funkcijos

 return_type (* name) (parameter_type_1, parameter_type_2, parameter_type_3) // ie f_int_t is a type: function pointer taking one int argument, returning int typedef int (*f_int_t) (int); // foo_p is a pointer to function taking int returning int // initialized by pointer to function foo taking int returning int int (* foo_p)(int) =  // can alternatively be written as f_int_t foo_p = > 

using deklaraciją galime šiek tiek geriau f_int_t , nes „ f_int_t taip pat gali būti parašytas taip:

 using f_int_t = int(*)(int); 

Kur (bent jau man) daugiau f_int_t kad f_int_t yra naujo tipo pseudonimas ir lengviau atpažinti funkcijų rodyklės tipą

Ir funkcijų deklaracija, naudojant funkcijų žymeklio tipą, bus:

 // foobar having a callback argument named moo of type // pointer to function returning int taking int as its argument int foobar (int x, int (*moo)(int)); // if f_int is the function pointer typedef from above we can also write foobar as: int foobar (int x, f_int_t moo); 

1.2 Atgalinis ryšys

Skambučio žymėjimas atitinka paprastą funkcijų skambučio sintaksę:

 int foobar (int x, int (*moo)(int)) { return x + moo(x); // function pointer moo called using argument x } // analog int foobar (int x, f_int_t moo) { return x + moo(x); // function pointer moo called using argument x } 

1.3 Atgalinio ryšio naudojimas ir suderinami tipai

Atgalinio ryšio funkcija, kuri priima rodyklę į funkciją, gali būti vadinama funkcijų rodyklėmis.

Naudojant funkciją, kuri priima funkcijų žymeklio atšaukimą, yra gana paprasta:

  int a = 5; int b = foobar(a, foo); // call foobar with pointer to foo as callback // can also be int b = foobar(a,  // call foobar with pointer to foo as callback 

1.4 Pavyzdys

Galite rašyti funkciją, kuri nepriklauso nuo to, kaip veikia atgalinio ryšio darbai:

 void tranform_every_int(int * v, unsigned n, int (*fp)(int)) { for (unsigned i = 0; i < n; ++i) { v[i] = fp(v[i]); } } 

jei įmanoma, gali būti

 int double_int(int x) { return 2*x; } int square_int(int x) { return x*x; } 

naudojamas kaip

 int a[5] = {1, 2, 3, 4, 5}; tranform_every_int( 5, double_int); // now a == {2, 4, 6, 8, 10}; tranform_every_int( 5, square_int); // now a == {4, 16, 36, 64, 100}; 

2. Rodyklės nario funkcija

Rodyklė nario funkcijai (kai kurioms C klasėms) yra specialus (ir dar sudėtingesnis) rodyklės tipas funkcijai, kurios veikimui reikalingas C tipo objektas.

 struct C { int y; int foo(int x) const { return x+y; } }; 

2.1 Rodyklės rašymas nario funkcijai / tipo žymėjimui

Rodyklė tam tikros T klasės nario funkcijos tipui žymima

 // can have more or less parameters return_type (T::*)(parameter_type_1, parameter_type_2, parameter_type_3) // ie a pointer to C::foo has the type int (C::*) (int) 

kur pavadinimo rodyklė nario funkcijai , kaip ir rodyklės funkcija, atrodys taip:

 return_type (T::* name) (parameter_type_1, parameter_type_2, parameter_type_3) // ie a type 'f_C_int' representing a pointer to member function of 'C' // taking int returning int is: typedef int (C::* f_C_int_t) (int x); // The type of C_foo_p is a pointer to member function of C taking int returning int // Its value is initialized by a pointer to foo of C int (C::* C_foo_p)(int) =  // which can also be written using the typedef: f_C_int_t C_foo_p = > 

Pavyzdys: funkcijos, kuri priima rodyklę į nario funkcijų atšaukimą , deklaravimas kaip vienas iš argumentų:

 // C_foobar having an argument named moo of type pointer to member function of C // where the callback returns int taking int as its argument // also needs an object of type c int C_foobar (int x, C const  int (C::*moo)(int)); // can equivalently declared using the typedef above: int C_foobar (int x, C const  f_C_int_t moo); 

2.2 Atgalinis ryšys

Rodyklė į nario funkciją C gali būti panaudota prieš C tipo objektą, naudojant elemento prieigos operaciją nukreiptoje rodyklėje. Pastaba: reikalingas laikiklis!

 int C_foobar (int x, C const  int (C::*moo)(int)) { return x + (c.*moo)(x); // function pointer moo called for object c using argument x } // analog int C_foobar (int x, C const  f_C_int_t moo) { return x + (c.*moo)(x); // function pointer moo called for object c using argument x } 

Pastaba: jei yra C rodyklė, sintaksė yra lygiavertė (kur C rodyklė turėtų būti nukreipta):

 int C_foobar_2 (int x, C const * c, int (C::*meow)(int)) { if (!c) return x; // function pointer meow called for object *c using argument x return x + ((*c).*meow)(x); } // or equivalent: int C_foobar_2 (int x, C const * c, int (C::*meow)(int)) { if (!c) return x; // function pointer meow called for object *c using argument x return x + (c->*meow)(x); } 

2.3 Atgalinio ryšio naudojimas ir suderinami tipai

Atšaukimo funkcija, kuri priima rodyklę į T klasės nario funkciją, gali būti vadinama rodikliu į T klasės nario funkciją

Naudojant funkciją, kuri gauna žymiklį į nario funkcijų atšaukimą, taip pat yra požymių funkcijos analogas:

  C my_c{2}; // aggregate initialization int a = 5; int b = C_foobar(a, my_c,  // call C_foobar with pointer to foo as its callback 

3. std::function objects ( <functional> antraštė)

std::function yra polimorfinė įvyniojimo funkcija, skirta saugoti, kopijuoti ar skambinti vadinamaisiais objektais.

3.1 Objekto std::function / type ženklo rašymas

std::function objekto, saugančio skambintą objektą, tipas atrodo taip:

 std::function<return_type(parameter_type_1, parameter_type_2, parameter_type_3)> // ie using the above function declaration of foo: std::function<int(int)> stdf_foo =  // or C::foo: std::function<int(const C int)> stdf_C_foo = > 

3.2 Atgalinis ryšys

Klasės std::function operator() kuris gali būti naudojamas norint remtis jūsų tikslu.

 int stdf_foobar (int x, std::function<int(int)> moo) { return x + moo(x); // std::function moo called } // or int stdf_C_foobar (int x, C const  std::function<int(C const  int)> moo) { return x + moo(c, x); // std::function moo called using c and x } 

3.3 Atgalinio ryšio naudojimas ir suderinami tipai

std::function atšaukimas yra bendresnis nei funkcijų rodyklės arba nario funkcijos rodyklė, nes skirtingi tipai gali būti perduoti ir netiesiogiai konvertuojami į std::function objektą.

3.3.1 Nuorodos į funkcijas ir nuorodas į narių funkcijas

Funkcijų žymeklis

 int a = 2; int b = stdf_foobar(a,  // b == 6 ( 2 + (2+2) ) 

arba rodyklė nario funkcijai

 int a = 2; C my_c{7}; // aggregate initialization int b = stdf_C_foobar(a, c,  // b == 11 == ( 2 + (7+2) ) 

galima naudoti.

3.3.2 Lambda išraiškos

Nenurodytas lambda išraiška gali būti saugomas std::function objekte:

 int a = 2; int c = 3; int b = stdf_foobar(a, [c](int x) -> int { return 7+c*x; }); // b == 15 == a + (7*c*a) == 2 + (7+3*2) 

3.3.3 std::bind išraiškos

Galima perduoti std::bind išraišką. Pvz., Susiejant parametrus su funkcijų žymeklio skambučiu:

 int foo_2 (int x, int y) { return 9*x + y; } using std::placeholders::_1; int a = 2; int b = stdf_foobar(a, std::bind(foo_2, _1, 3)); // b == 23 == 2 + ( 9*2 + 3 ) int c = stdf_foobar(a, std::bind(foo_2, 5, _1)); // c == 49 == 2 + ( 9*5 + 2 ) 

Kur taip pat galima prijungti objektus kaip objektą, norėdami paskambinti į nario funkcijas:

 int a = 2; C const my_c{7}; // aggregate initialization int b = stdf_foobar(a, std::bind( my_c, _1)); // b == 1 == 2 + ( 2 + 7 ) 

3.3.4 Funkciniai objektai

Klasių, turinčių tinkamą operator() perkrovą, objektai gali būti saugomi objekto std::function .

 struct Meow { int y = 0; Meow(int y_) : y(y_) {} int operator()(int x) { return y * x; } }; int a = 11; int b = stdf_foobar(a, Meow{8}); // b == 99 == 11 + ( 8 * 11 ) 

3.4 Pavyzdys

Pavyzdinio funkcijų rodyklės keitimas, norint naudoti std::function

 void stdf_tranform_every_int(int * v, unsigned n, std::function<int(int)> fp) { for (unsigned i = 0; i < n; ++i) { v[i] = fp(v[i]); } } 

suteikia daug daugiau naudos šiai funkcijai, nes (žr. 3.3) turime daugiau galimybių ją naudoti:

 // using function pointer still possible int a[5] = {1, 2, 3, 4, 5}; stdf_tranform_every_int( 5, double_int); // now a == {2, 4, 6, 8, 10}; // use it without having to write another function by using a lambda stdf_tranform_every_int( 5, [](int x) -> int { return x/2; }); // now a == {1, 2, 3, 4, 5}; again // use std::bind : int nine_x_and_y (int x, int y) { return 9*x + y; } using std::placeholders::_1; // calls nine_x_and_y for every int in a with y being 4 every time stdf_tranform_every_int( 5, std::bind(nine_x_and_y, _1, 4)); // now a == {13, 22, 31, 40, 49}; 

4. Šablono atgalinio ryšio tipas

Naudojant modelius, kodas, kuris skambina atgaline data, gali būti dar bendresnis nei naudojant std::function objektus.

Atkreipkite dėmesį, kad šablonai yra kompiliavimo laiko ir kompiliavimo laiko polimorfizmo projektavimo priemonė. Jei dinaminis elgesys važiavimo metu turėtų būti pasiektas naudojant atšaukimus, šablonai padės, tačiau jie nesukels dinamikos važiavimo metu.

4.1 Rašymas (tipo pavadinimas) ir skambučių atšaukimai

Apibendrinimas, t.y. Šį std_ftransform_every_int kodą std_ftransform_every_int galima pasiekti dar labiau naudojant šablonus:

 template<class R, class T> void stdf_transform_every_int_templ(int * v, unsigned const n, std::function<R(T)> fp) { for (unsigned i = 0; i < n; ++i) { v[i] = fp(v[i]); } } 

su dar bendresne (ir taip pat paprasčiausiomis) atšaukimo tipo sintaksėmis, kuri yra paprastas, bendrasis išeinantis argumentas:

 template<class F> void transform_every_int_templ(int * v, unsigned const n, F f) { std::cout << "transform_every_int_templ<" << type_name<F>() << ">\n"; for (unsigned i = 0; i < n; ++i) { v[i] = f(v[i]); } } 

Pastaba: įtrauktas išvestis išspausdina tipo pavadinimą, atspausdintą F šablono tipui.

Dažniausias vienarūšio diapazono transformacijos įgyvendinimas yra standartinės bibliotekos dalis, būtent std::transform , kuri taip pat yra kartotinių tipų šablonas.

 template<class InputIt, class OutputIt, class UnaryOperation> OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op) { while (first1 != last1) { *d_first++ = unary_op(*first1++); } return d_first; } 

4.2 Pavyzdinių skambučių ir suderinamų tipų naudojimo pavyzdžiai

Suderinami šablono atšaukimo metodo std::function stdf_transform_every_int_templ identiški pirmiau nurodytiems tipams (žr. 3.4).

Tačiau, naudojant šablono versiją, naudojamas atšaukimo atgalinis parašas gali šiek tiek pasikeisti:

 // Let int foo (int x) { return 2+x; } int muh (int const  { return 3+x; } int  woof (int  { x *= 4; return x; } int a[5] = {1, 2, 3, 4, 5}; stdf_transform_every_int_templ<int,int>( 5,  // a == {3, 4, 5, 6, 7} stdf_transform_every_int_templ<int, int const  5,  // a == {6, 7, 8, 9, 10} stdf_transform_every_int_templ<int, int  5, > 

Pastaba: std_ftransform_every_int (ne šablono versija; žr. Aukščiau) veikia su foo bet nenaudoja muh .

 // Let void print_int(int * p, unsigned const n) { bool f{ true }; for (unsigned i = 0; i < n; ++i) { std::cout << (f ? "" : " ") << p[i]; f = false; } std::cout << "\n"; } 

Paprastas šablono parametras transform_every_int_templ gali būti bet koks galimas prašomas tipas.

 int a[5] = { 1, 2, 3, 4, 5 }; print_int(a, 5); transform_every_int_templ( 5, foo); print_int(a, 5); transform_every_int_templ( 5, muh); print_int(a, 5); transform_every_int_templ( 5, woof); print_int(a, 5); transform_every_int_templ( 5, [](int x) -> int { return x + x + x; }); print_int(a, 5); transform_every_int_templ( 5, Meow{ 4 }); print_int(a, 5); using std::placeholders::_1; transform_every_int_templ( 5, std::bind(foo_2, _1, 3)); print_int(a, 5); transform_every_int_templ( 5, std::function<int(int)>{ print_int(a, 5); 

Pirmiau nurodytas kodas išspausdinamas:

 1 2 3 4 5 transform_every_int_templ <int(*)(int)> 3 4 5 6 7 transform_every_int_templ <int(*)(int 6 8 10 12 14 transform_every_int_templ <int (*)(int 9 11 13 15 17 transform_every_int_templ <main::{lambda(int)#1} > 27 33 39 45 51 transform_every_int_templ <Meow> 108 132 156 180 204 transform_every_int_templ <std::_Bind<int(*(std::_Placeholder<1>, int))(int, int)>> 975 1191 1407 1623 1839 transform_every_int_templ <std::function<int(int)>> 977 1193 1409 1625 1841 

type_name naudojamas type_name

 #include <type_traits> #include <typeinfo> #include <string> #include <memory> #include <cxxabi.h> template <class T> std::string type_name() { typedef typename std::remove_reference<T>::type TR; std::unique_ptr<char, void(*)(void*)> own (abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr), std::free); std::string r = own != nullptr?own.get():typeid(TR).name(); if (std::is_const<TR>::value) r += " const"; if (std::is_volatile<TR>::value) r += " volatile"; if (std::is_lvalue_reference<T>::value) r += "  else if (std::is_rvalue_reference<T>::value) r += "  return r; } 
319
24 февр. Atsakymą Pixelchemist pateikė vasario 24 d. 2015-02-24 10:02 '15 at 10:02 am 2015-02-24 10:02

Taip pat yra būdas C atšaukti: funkcijų rodyklės

 //Define a type for the callback signature, //it is not necessary, but makes life easier //Function pointer called CallbackType that takes a float //and returns an int typedef int (*CallbackType)(float); void DoWork(CallbackType callback) { float variable = 0.0f; //Do calculations //Call the callback with the variable, and retrieve the //result int result = callback(variable); //Do something with the result } int SomeCallback(float variable) { int result; //Interpret variable return result; } int main(int argc, char ** argv) { //Pass in SomeCallback to the DoWork DoWork( } 

Dabar, jei norite perduoti klasių metodus kaip atšaukimus, šių funkcijų rodiklių deklaracijose yra sudėtingesnės deklaracijos, pavyzdžiui:

 //Declaration: typedef int (ClassName::*CallbackType)(float); //This method performs work using an object instance void DoWorkObject(CallbackType callback) { //Class instance to invoke it through ClassName objectInstance; //Invocation int result = (objectInstance.*callback)(1.0f); } //This method performs work using an object pointer void DoWorkPointer(CallbackType callback) { //Class pointer to invoke it through ClassName * pointerInstance; //Invocation int result = (pointerInstance->*callback)(1.0f); } int main(int argc, char ** argv) { //Pass in SomeCallback to the DoWork DoWorkObject( DoWorkPointer( } 
147
19 февр. Atsakymą pateikė Ramon Zarazua B. 19 vasaris. 2010-02-19 22:06 '10 10:06 val. 2010-02-19 22:06

Scott Meyers pateikia gerą pavyzdį:

 class GameCharacter; int defaultHealthCalc(const GameCharacter gc); class GameCharacter { public: typedef std::function<int (const GameCharacter HealthCalcFunc; explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) : healthFunc(hcf) { } int healthValue() const { return healthFunc(*this); } private: HealthCalcFunc healthFunc; }; 

Manau, kad šis pavyzdys viską pasakoja.

std::function<> yra „šiuolaikinis“ C ++ skambinimo būdas.

63
19 февр. atsakymą pateikė Karl von Moor , vasario 19 d. 2010-02-19 20:23 '10, 20:23, 2010-02-19 20:23

Atgalinio atšaukimo funkcija yra metodas, kuris perduodamas į paprogramę ir tam tikru momentu vadinamas paprogramiu, kuriam jis perduotas.

Tai labai naudinga kuriant daugkartinio naudojimo programinę įrangą. Pvz., Daugelis operacinių sistemų API (pvz., „Windows API“) dažniausiai naudoja „callbacks“.

Pvz., Jei norite dirbti su aplanke esančiais failais, galite paskambinti API funkcija, naudodami savo procedūrą, ir jūsų procedūra vykdoma vieną kartą kiekvienam failui nurodytame aplanke. Tai leidžia API būti labai lanksti.

37
19 февр. atsakymą pateikė Reed Copsey vasario 19 d 2010-02-19 20:20 '10, 20:20, 2010-02-19 20:20

Priimtas atsakymas yra labai naudingas ir gana išsamus. Tačiau OP nustato

Norėčiau matyti paprastą pavyzdį, kaip parašyti atgalinio ryšio funkciją.

Taigi, čia jūs esate, iš C ++ 11 turite std::function , todėl nereikia funkcijų rodyklių ir panašių medžiagų:

 #include <functional> #include <string> #include <iostream> void print_hashes(std::function<int (const std::string hash_calculator) { std::string strings_to_hash[] = {"you", "saved", "my", "day"}; for(auto s : strings_to_hash) std::cout << s << ":" << hash_calculator(s) << std::endl; } int main() { print_hashes( [](const std::string str) {  int result = 0; for (int i = 0; i < str.length(); i++) result += pow(31, i) * str.at(i); return result; }); return 0; } 

Beje, šis pavyzdys yra kažkaip realus, nes norite paskambinti print_hashes funkcija skirtingais maišos funkcijų įgyvendinimais, tam tikslui pateikiau paprastą. Jis gauna eilutę, grąžina int (pateiktos eilutės maišos vertė), ir viskas, ką reikia prisiminti iš sintaksės yra std::function<int (const std::string> , kuri apibūdina tokią funkciją kaip įvestis funkcijos, kuri ją pavadins, argumentas.

9
01 июля '16 в 23:36 2016-07-01 23:36 atsakymą pateikė Miljen Mikic liepos 1 d. 16 d. 23:36 2016-07-01 23:36

C ++ sistemoje nėra aiškios atgalinio ryšio funkcijos koncepcijos. Atgalinio ryšio mechanizmai dažnai įgyvendinami naudojant funkcijų rodykles, funktorių objektus arba atgalinio ryšio objektus. Programuotojai turi aiškiai sukurti ir įdiegti atgalinio ryšio funkcijas.

Pakeisti pagal atsiliepimus:

Nepaisant neigiamų atsiliepimų, gautų atsakant, tai nėra. Bandysiu geriau paaiškinti, iš kur aš esu.

„C“ ir „C ++“ turi viską, ko reikia, kad įdiegtumėte atgalinio ryšio funkcijas. Наиболее распространенным и тривиальным способом реализации функции обратного вызова является передача указателя функции в качестве аргумента функции.