C++

Fungsi Panggilan Balik di C++

Fungsi Panggilan Balik di C++

Fungsi panggilan balik adalah fungsi, yang merupakan argumen, bukan parameter, di fungsi lain. Fungsi lainnya dapat disebut fungsi utama. Jadi dua fungsi terlibat: fungsi utama dan fungsi panggilan balik itu sendiri. Dalam daftar parameter fungsi utama, ada deklarasi fungsi panggilan balik tanpa definisinya, sama seperti deklarasi objek tanpa penetapan. Fungsi utama dipanggil dengan argumen (dalam main()). Salah satu argumen dalam panggilan fungsi utama adalah definisi efektif dari fungsi panggilan balik. Dalam C++, argumen ini adalah referensi ke definisi fungsi panggilan balik; itu bukan definisi sebenarnya. Fungsi panggilan balik itu sendiri sebenarnya dipanggil dalam definisi fungsi utama.

Fungsi panggilan balik dasar dalam C++ tidak menjamin perilaku asinkron dalam suatu program.  Perilaku asinkron adalah manfaat nyata dari skema fungsi panggilan balik. Dalam skema fungsi panggilan balik asinkron, hasil fungsi utama harus diperoleh untuk program sebelum hasil fungsi panggilan balik diperoleh. Dimungkinkan untuk melakukan ini di C++; namun, C++ memiliki pustaka yang disebut masa depan untuk menjamin perilaku skema fungsi panggilan balik asinkron.

Artikel ini menjelaskan skema fungsi panggilan balik dasar. Banyak dengan C . murni++. Sejauh menyangkut panggilan balik, perilaku dasar perpustakaan masa depan juga dijelaskan. Pengetahuan dasar tentang C++ dan petunjuknya diperlukan untuk memahami artikel ini.

Isi Artikel

Skema Fungsi Panggilan Balik Dasar

Skema fungsi panggilan balik membutuhkan fungsi utama, dan fungsi panggilan balik itu sendiri. Deklarasi fungsi panggilan balik adalah bagian dari daftar parameter fungsi utama. Definisi fungsi panggilan balik ditunjukkan dalam panggilan fungsi dari fungsi utama. Fungsi panggilan balik sebenarnya dipanggil dalam definisi fungsi utama. Program berikut menggambarkan hal ini:

#termasuk
menggunakan namespace std;
int prinsipFn(char ch[], int (*ptr)(int))

int id1 = 1;
int id2 = 2;
int idr = (*ptr)(id2);
cout<<"principal function: "<kembali id1;

int cb(int ident)

cout<<"callback function"<<'\n';
kembali ident;

int utama()

int (*ptr)(int) = &cb;
char cha[] = "dan";
prinsipalFn(cha, cb);
kembali 0;

Outputnya adalah:

fungsi panggilan balik
fungsi utama: 1 dan 2

Fungsi utama diidentifikasi oleh principalFn(). Fungsi panggilan balik diidentifikasi oleh cb(). Fungsi panggilan balik didefinisikan di luar fungsi utama tetapi sebenarnya dipanggil di dalam fungsi utama.

Perhatikan deklarasi fungsi panggilan balik sebagai parameter dalam daftar parameter deklarasi fungsi utama. Deklarasi fungsi callback adalah “int (*ptr)(int)”. Perhatikan ekspresi fungsi panggilan balik, seperti panggilan fungsi, dalam definisi fungsi utama; argumen apa pun untuk panggilan fungsi panggilan balik dilewatkan di sana. Pernyataan untuk pemanggilan fungsi ini adalah:

int idr = (*ptr)(id2);

Di mana id2 adalah argumen. ptr adalah bagian dari parameter, pointer, yang akan ditautkan ke referensi fungsi callback di fungsi main().

Perhatikan ungkapan:

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

Dalam fungsi main(), yang menautkan deklarasi (tanpa definisi) fungsi panggilan balik ke nama definisi fungsi panggilan balik yang sama.

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

prinsipalFn(cha, cb);

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

Perilaku Sinkron dari Fungsi Panggilan Balik

Perhatikan program berikut:

#termasuk
menggunakan namespace std;
void principalFn(void (*ptr)())

cout<<"principal function"<<'\n';
(*ptr)();

batal cb()

cout<<"callback function"<<'\n';

batal fn()

cout<<"seen"<<'\n';

int utama()

batal (*ptr)() = &cb;
prinsipalFn(cb);
fn();
kembali 0;

Outputnya adalah:

fungsi utama
fungsi panggilan balik
terlihat

Ada fungsi baru di sini. Semua fungsi baru dilakukan, adalah untuk menampilkan output, "terlihat". Dalam fungsi main(), fungsi utama dipanggil, kemudian fungsi baru, fn() dipanggil. Outputnya menunjukkan bahwa kode untuk fungsi utama dieksekusi, kemudian untuk fungsi panggilan balik dieksekusi, dan akhirnya untuk fungsi fn() dieksekusi. Ini adalah perilaku sinkron (berulir tunggal).

Jika itu adalah perilaku asinkron, ketika tiga segmen kode dipanggil secara berurutan, segmen kode pertama dapat dieksekusi, diikuti oleh eksekusi segmen kode ketiga, sebelum segmen kode kedua dieksekusi.

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

#termasuk
menggunakan namespace std;
batal fn()

cout<<"seen"<<'\n';

batal prinsipFn(batal (*ptr)())

cout<<"principal function"<<'\n';
fn();
(*ptr)();

batal cb()

cout<<"callback function"<<'\n';

int utama()

batal (*ptr)() = &cb;
prinsipalFn(cb);
kembali 0;

Outputnya adalah:

fungsi utama
terlihat
fungsi panggilan balik

Ini adalah tiruan dari perilaku asinkron. Ini bukan perilaku asinkron. Itu masih perilaku sinkron.

Juga, urutan eksekusi segmen kode fungsi utama dan segmen kode fungsi panggilan balik dapat ditukar dalam definisi fungsi utama. Program berikut menggambarkan hal ini:

#termasuk
menggunakan namespace std;
 
void principalFn(void (*ptr)())

(*ptr)();
cout<<"principal function"<<'\n';

batal cb()

cout<<"callback function"<<'\n';

batal fn()

cout<<"seen"<<'\n';

int utama()

batal (*ptr)() = &cb;
prinsipalFn(cb);
fn();
kembali 0;

Outputnya sekarang,

fungsi panggilan balik
fungsi utama
terlihat

Ini juga merupakan tiruan dari perilaku asinkron. Ini bukan perilaku asinkron. Itu masih perilaku sinkron. Perilaku asinkron yang sebenarnya dapat diperoleh seperti yang dijelaskan di bagian selanjutnya atau dengan perpustakaan, di masa mendatang.

Perilaku Asinkron dengan Fungsi Panggilan Balik

Kode semu untuk skema fungsi panggilan balik asinkron dasar adalah:

jenis keluaran;
ketik cb (ketik keluaran)

//pernyataan

ketik principalFn(ketik masukan, ketik cb(ketik keluaran))

//pernyataan

Perhatikan posisi data input dan output di tempat yang berbeda dari pseudo-code. Input dari fungsi panggilan balik adalah outputnya. Parameter fungsi utama adalah parameter input untuk kode umum dan parameter untuk fungsi panggilan balikback. Dengan skema ini, fungsi ketiga dapat dieksekusi (dipanggil) di fungsi main() sebelum output dari fungsi callback dibaca (masih di fungsi main()). Kode berikut menggambarkan hal ini:

#termasuk
menggunakan namespace std;
karakter *keluaran;
batalkan cb (habiskan [])

keluaran = keluar;

void principalFn(char input[], void (*ptr)(char[50]))

(*ptr)(masukan);
cout<<"principal function"<<'\n';

batal fn()

cout<<"seen"<<'\n';

int utama()

char input[] = "fungsi panggilan balik";
void (*ptr)(char[]) = &cb;
prinsipFn(masukan, cb);
fn();
cout<kembali 0;

Keluaran programnya adalah:

fungsi utama
terlihat
fungsi panggilan balik

Dalam kode khusus ini, datum keluaran dan masukan kebetulan adalah datum yang sama. Hasil pemanggilan fungsi ketiga dalam fungsi main() telah ditampilkan sebelum hasil dari fungsi pemanggilan balik. Fungsi panggilan balik dieksekusi, selesai, dan menetapkan hasilnya (nilai) ke variabel, output, memungkinkan program untuk melanjutkan tanpa gangguannya. Dalam fungsi main(), output dari fungsi panggilan balik digunakan (dibaca dan ditampilkan) saat dibutuhkan, yang mengarah ke perilaku asinkron untuk keseluruhan skema.

Ini adalah cara utas tunggal untuk mendapatkan perilaku asinkron fungsi panggilan balik dengan C . murni++.

Penggunaan dasar Perpustakaan masa depan

Gagasan skema fungsi panggilan balik asinkron adalah bahwa fungsi utama kembali sebelum fungsi panggilan balik kembali. Ini dilakukan secara tidak langsung, efektif, dalam kode di atas.

Perhatikan dari kode di atas bahwa fungsi callback menerima input utama untuk kode dan menghasilkan output utama untuk kode. Pustaka C++, di masa mendatang, memiliki fungsi yang disebut sync(). Argumen pertama untuk fungsi ini adalah referensi fungsi panggilan balik; argumen kedua adalah input ke fungsi panggilan balik. Fungsi sync() kembali tanpa menunggu eksekusi fungsi callback selesai tetapi memungkinkan fungsi callback selesai. Ini memberikan perilaku asinkron. Sementara fungsi callback terus dijalankan, karena fungsi sync() telah kembali, pernyataan di bawahnya terus dijalankan. Ini seperti perilaku asinkron yang ideal.

Program di atas telah ditulis ulang di bawah ini, dengan mempertimbangkan pustaka masa depan dan fungsi sync()-nya:

#termasuk
#termasuk
#termasuk
menggunakan namespace std;
masa depan keluaran;
string cb (string stri)

kembali stri;

batalkan prinsipalFn (input string)

keluaran = asinkron(cb, masukan);
cout<<"principal function"<<'\n';

batal fn()

cout<<"seen"<<'\n';

int utama()

string masukan = string("fungsi panggilan balik");
prinsipFn(masukan);
fn();
string ret = keluaran.Dapatkan(); //menunggu panggilan balik untuk kembali jika perlu
cout<kembali 0;

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

Kesimpulan

Fungsi panggilan balik adalah fungsi, yang merupakan argumen, bukan parameter, di fungsi lain. Skema fungsi panggilan balik membutuhkan fungsi utama, dan fungsi panggilan balik itu sendiri. Deklarasi fungsi panggilan balik adalah bagian dari daftar parameter fungsi utama. Definisi fungsi callback ditunjukkan dalam pemanggilan fungsi dari fungsi utama (dalam main()). Fungsi panggilan balik sebenarnya dipanggil dalam definisi fungsi utama.

Skema fungsi panggilan balik belum tentu asinkron. Untuk memastikan bahwa skema fungsi panggilan balik tidak sinkron, buat input utama ke kode, input ke fungsi panggilan balik; buat output utama dari kode, output dari fungsi panggilan balik; menyimpan output dari fungsi panggilan balik dalam variabel atau struktur data. Dalam fungsi main(), setelah memanggil fungsi utama, jalankan pernyataan lain dari aplikasi. Ketika output dari fungsi callback diperlukan, dalam fungsi main(), gunakan (baca dan tampilkan) di sana dan kemudian.

Shadow of the Tomb Raider untuk Tutorial Linux
Shadow of the Tomb Raider adalah tambahan kedua belas untuk seri Tomb Raider - waralaba game aksi-petualangan yang dibuat oleh Eidos Montreal. Permain...
Cara Meningkatkan FPS di Linux?
FPS adalah singkatan dari Bingkai per detik. Tugas FPS adalah mengukur kecepatan bingkai dalam pemutaran video atau pertunjukan game. Dengan kata sede...
Game Lab Aplikasi Oculus Teratas
Jika Anda adalah pemilik headset Oculus maka Anda harus tahu tentang sideloading. Sideloading adalah proses menginstal konten non-toko di headset Anda...