Fungsi Panggilan Balik dalam C ++

Callback Function C



Fungsi callback adalah fungsi, yang merupakan argumen, bukan parameter, dalam fungsi lain. Fungsi lain boleh dipanggil fungsi utama. Oleh itu, dua fungsi terlibat: fungsi utama dan fungsi panggilan balik itu sendiri. Dalam senarai parameter fungsi utama, pernyataan fungsi panggilan balik tanpa definisinya ada, sama seperti pernyataan objek tanpa penugasan yang ada. Fungsi utama dipanggil dengan argumen (dalam utama ()). Salah satu argumen dalam fungsi panggilan utama adalah definisi berkesan fungsi panggilan balik. Dalam C ++, argumen ini merujuk kepada definisi fungsi panggilan balik; itu bukan definisi sebenarnya. Fungsi panggil balik itu sendiri sebenarnya disebut dalam definisi fungsi utama.

Fungsi panggilan balik asas dalam C ++ tidak menjamin tingkah laku tidak segerak dalam program. Tingkah laku tak segerak adalah faedah sebenar dari skema fungsi panggilan balik. Dalam skema fungsi panggilan balik tak segerak, hasil fungsi utama harus diperoleh untuk program sebelum hasil fungsi panggilan balik diperoleh. Ada kemungkinan untuk melakukan ini di C ++; namun, C ++ mempunyai perpustakaan yang disebut masa depan untuk menjamin tingkah laku skema fungsi panggilan balik tak segerak.







Artikel ini menerangkan skema fungsi panggilan balik asas. Sebilangan besar dengan C ++ tulen. Mengenai panggilan balik, tingkah laku asas perpustakaan masa depan juga dijelaskan. Pengetahuan asas mengenai C ++ dan petunjuknya diperlukan untuk pemahaman artikel ini.



Kandungan Artikel

Skim Fungsi Panggilan Balik Asas

Skema fungsi panggilan balik memerlukan fungsi utama, dan fungsi panggilan balik itu sendiri. Pengisytiharan fungsi panggilan balik adalah sebahagian daripada senarai parameter fungsi utama. Definisi fungsi panggilan balik ditunjukkan dalam fungsi panggilan fungsi utama. Fungsi panggil balik sebenarnya dipanggil dalam definisi fungsi utama. Program berikut menggambarkan ini:



#sertakan

menggunakan ruang namaJam;



intutamaFn(charch[],int (*ptr)(int))

{

intid1= 1;

intid2= 2;

intbiasanya= (*ptr)(id2);

kos<<'fungsi utama:'<<id1<<''<<ch<<''<<biasanya<<' n';

kembaliid1;

}


intcb(intiden)

{

kos<<'fungsi panggilan balik'<<' n';

kembaliiden;

}


intutama()

{

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

chartidak[] = 'dan';

utamaFn(bapa, cb);



kembali 0;

}

Keluarannya adalah:





fungsi panggilan balik

fungsi pokok: 1 dan 2

Fungsi utama dikenal pasti oleh principalFn (). Fungsi panggil balik dikenal pasti oleh cb (). Fungsi panggil balik ditentukan di luar fungsi utama tetapi sebenarnya dipanggil dalam fungsi utama.

Perhatikan deklarasi fungsi panggilan balik sebagai parameter dalam senarai parameter deklarasi fungsi utama. Pengisytiharan fungsi panggilan balik adalah int (* ptr) (int). Perhatikan ungkapan fungsi panggilan balik, seperti fungsi panggilan, dalam definisi fungsi utama; sebarang hujah untuk panggilan fungsi panggilan balik disampaikan di sana. Pernyataan untuk panggilan fungsi ini adalah:



intbiasanya= (*ptr)(id2);

Di mana id2 adalah hujah. ptr adalah sebahagian dari parameter, penunjuk, yang akan dihubungkan dengan rujukan fungsi panggilan balik dalam fungsi utama ().

Perhatikan ungkapan:

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

Dalam fungsi utama (), yang menghubungkan pengisytiharan (tanpa definisi) fungsi panggilan balik dengan nama definisi fungsi panggilan balik yang sama.

Fungsi utama dipanggil, dalam fungsi utama (), sebagai:

utamaFn(bapa, cb);

Di mana cha adalah rentetan dan cb adalah nama fungsi panggilan balik tanpa ada argumennya.

Tingkah Laku Fungsi Panggilan Balik

Pertimbangkan program berikut:

#sertakan

menggunakan ruang namaJam;



batalutamaFn(batal (*ptr)())

{

kos<<'fungsi utama'<<' n';

(*ptr)();

}


batalcb()

{

kos<<'fungsi panggilan balik'<<' n';

}


batalfn()

{

kos<<'dilihat'<<' n';

}


intutama()

{

batal (*ptr)() = &cb;

utamaFn(cb);

fn();



kembali 0;

}

Keluarannya adalah:

fungsi pokok

fungsi panggilan balik

dilihat

Terdapat fungsi baru di sini. Semua fungsi baru yang dilakukan adalah untuk menampilkan output, dilihat. Dalam fungsi utama (), fungsi utama dipanggil, kemudian fungsi baru, fn () dipanggil. Output menunjukkan bahawa kod untuk fungsi utama telah dijalankan, kemudian untuk fungsi panggilan balik dijalankan, dan akhirnya untuk fungsi fn () dijalankan. Ini adalah tingkah laku segerak (utas tunggal).

Sekiranya itu adalah tingkah laku asinkron, ketika tiga segmen kod dipanggil dalam urutan, segmen kod pertama dapat dijalankan, diikuti oleh pelaksanaan segmen kod ketiga, sebelum segmen kod kedua dijalankan.

Nah, fungsi, fn () dapat dipanggil dari dalam definisi fungsi utama, bukan dari dalam fungsi utama (), seperti berikut:

#sertakan

menggunakan ruang namaJam;



batalfn()

{

kos<<'dilihat'<<' n';

}


batalutamaFn(batal (*ptr)())

{

kos<<'fungsi utama'<<' n';

fn();

(*ptr)();

}


batalcb()

{

kos<<'fungsi panggilan balik'<<' n';

}


intutama()

{

batal (*ptr)() = &cb;

utamaFn(cb);



kembali 0;

}

Keluarannya adalah:

fungsi pokok

dilihat

fungsi panggilan balik

Ini adalah tiruan daripada tingkah laku tidak segerak. Ia bukan tingkah laku tidak segerak. Itu masih tingkah laku segerak.

Juga, urutan pelaksanaan segmen kod fungsi utama dan segmen kod fungsi panggilan balik dapat ditukar dalam definisi fungsi utama. Program berikut menggambarkan ini:

#sertakan

menggunakan ruang namaJam;



batalutamaFn(batal (*ptr)())

{

(*ptr)();

kos<<'fungsi utama'<<' n';

}


batalcb()

{

kos<<'fungsi panggilan balik'<<' n';

}


batalfn()

{

kos<<'dilihat'<<' n';

}


intutama()

{

batal (*ptr)() = &cb;

utamaFn(cb);

fn();



kembali 0;

}

Keluarannya sekarang,

fungsi panggilan balik

fungsi pokok

dilihat

Ini juga merupakan tiruan daripada tingkah laku tak segerak. Ia bukan tingkah laku tidak segerak. Itu masih tingkah laku segerak. Tingkah laku asinkron yang benar dapat diperoleh seperti yang dijelaskan di bahagian seterusnya atau dengan perpustakaan, di masa depan.

Tingkah Laku tak segerak dengan Fungsi Panggilan Balik

Kod pseudo untuk skema fungsi panggilan balik asinkron asas adalah:

keluarkan jenis;

taip cb(keluarkan jenis)

{

// penyataan

}


taip prinsipalFn(taip input, taip cb(keluarkan jenis))

{

// penyataan

}

Perhatikan kedudukan data input dan output di tempat berlainan kod pseudo. Input fungsi panggilan balik adalah outputnya. Parameter fungsi utama adalah parameter input untuk kod umum dan parameter untuk fungsi panggilan balik. Dengan skema ini, fungsi ketiga dapat dijalankan (disebut) dalam fungsi utama () sebelum output fungsi panggilan balik dibaca (masih dalam fungsi utama ()). Kod berikut menggambarkan ini:

#sertakan

menggunakan ruang namaJam;

char *pengeluaran;


batalcb(charkeluar[])

{

pengeluaran=keluar;

}



batalutamaFn(charinput[],batal (*ptr)(char[lima puluh]))

{

(*ptr)(input);

kos<<'fungsi utama'<<' n';

}


batalfn()

{

kos<<'dilihat'<<' n';

}


intutama()

{

charinput[] = 'fungsi panggilan balik';

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

utamaFn(input, cb);

fn();

kos<<pengeluaran<<' n';



kembali 0;

}

Output program adalah:

fungsi pokok

dilihat

fungsi panggilan balik

Dalam kod ini, datum output dan input kebetulan adalah datum yang sama. Hasil panggilan fungsi ketiga dalam fungsi utama () telah ditampilkan sebelum hasil fungsi panggilan balik. Fungsi panggil balik dilaksanakan, selesai, dan memberikan hasilnya (nilai) ke pemboleh ubah, output, yang membolehkan program diteruskan tanpa gangguannya. Dalam fungsi utama (), output fungsi panggilan balik digunakan (dibaca dan ditampilkan) ketika diperlukan, yang menyebabkan tingkah laku tidak segerak untuk keseluruhan skema.

Ini adalah kaedah utas tunggal untuk mendapatkan kelakuan asinkron fungsi panggilan balik dengan C ++ tulen.

Penggunaan asas Perpustakaan masa depan

Idea skema fungsi panggilan balik tidak segerak adalah bahawa fungsi utama kembali sebelum fungsi panggilan balik kembali. Ini dilakukan secara tidak langsung, berkesan, dalam kod di atas.

Perhatikan dari kod di atas bahawa fungsi panggilan balik menerima input utama untuk kod dan menghasilkan output utama untuk kod tersebut. Perpustakaan C ++, di masa depan, mempunyai fungsi yang disebut sync (). Argumen pertama untuk fungsi ini adalah rujukan fungsi panggilan balik; argumen kedua adalah input untuk fungsi panggilan balik. Fungsi sync () kembali tanpa menunggu pelaksanaan fungsi callback selesai tetapi membolehkan fungsi callback selesai. Ini memberikan tingkah laku tidak segerak. Walaupun fungsi panggilan balik terus dijalankan, kerana fungsi sinkronisasi () sudah kembali, pernyataan di bawahnya terus dilaksanakan. Ini seperti tingkah laku tak segerak yang ideal.

Program di atas telah ditulis semula di bawah, dengan mempertimbangkan perpustakaan masa depan dan fungsi penyegerakannya ():

#sertakan

#sertakan

#sertakan

menggunakan ruang namaJam;

masa depan<tali>pengeluaran;

tali cb(rentetan rentetan)

{

kembaliberusaha;

}



batalutamaFn(input rentetan)

{

pengeluaran=tidak segerak(cb, input);

kos<<'fungsi utama'<<' n';

}


batalfn()

{

kos<<'dilihat'<<' n';

}


intutama()

{

input rentetan=tali('fungsi panggilan balik');

utamaFn(input);

fn();

tali ret=pengeluaran.dapatkan(); // menunggu panggilan balik kembali jika perlu

kos<<betul<<' n';



kembali 0;

}

Fungsi sync () akhirnya menyimpan output fungsi callback ke objek masa depan. Output yang diharapkan dapat diperoleh dalam fungsi utama (), menggunakan fungsi anggota get () dari objek masa depan.

Kesimpulannya

Fungsi callback adalah fungsi, yang merupakan argumen, bukan parameter, dalam fungsi lain. Skema fungsi panggilan balik memerlukan fungsi utama, dan fungsi panggilan balik itu sendiri. Pengisytiharan fungsi panggilan balik adalah sebahagian daripada senarai parameter fungsi utama. Definisi fungsi panggilan balik ditunjukkan dalam fungsi panggilan fungsi utama (dalam utama ()). Fungsi panggil balik sebenarnya dipanggil dalam definisi fungsi utama.

Skema fungsi panggilan balik tidak semestinya segerak. Untuk memastikan bahawa skema fungsi panggilan balik tidak segerak, buat input utama ke kod, input ke fungsi panggilan balik; membuat output utama kod, output fungsi panggilan balik; menyimpan output fungsi panggilan balik dalam pemboleh ubah atau struktur data. Dalam fungsi utama (), setelah memanggil fungsi utama, jalankan pernyataan aplikasi yang lain. Apabila output fungsi panggilan balik diperlukan, dalam fungsi utama (), gunakan (baca dan paparkan) di sana dan kemudian.