Fungsi Panggilan Balik di C++

Fungsi Panggilan Balik di C++

Fungsi panggilan balik adalah fungsi, yang merupakan argumen, bukan parameter, dalam 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 di 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 dari itu 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:

#include <iostream>

using namespace std;

 

int principalFn(char ch[], int (*ptr)(int))

    {

        int id1 = 1;

        int id2 = 2;

        int idr = (*ptr)(id2);

        cout<<"principal function: "<<id1<<' '<<ch<<' '<<idr<<'n';

        return id1;

    }


int cb(int iden)

    {

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

        return iden;

    }


int main()

{

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

    char cha[] = "and";

    principalFn(cha, cb);

 

   return 0;

}

Outputnya adalah:

    callback function

    principal function: 1 and 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.

Catat deklarasi fungsi callback 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, sebuah 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:

    principalFn(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:

#include <iostream>

using namespace std;

 

void pr incipalFn(void (*ptr)())

    {

        cout<<"principal function"<<'n';

        (*ptr)();

    }


void cb()

    {

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

    }


void fn()

    {

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

    }


int main()

{

    void (*ptr)() = &cb;

    principalFn(cb);

    fn();

 

   return 0;

}

Outputnya adalah:

    principal function

    callback function

    seen

Ada fungsi baru di sini. Semua fungsi baru yang 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 terakhir 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:

#include <iostream>

using namespace std;

 

void fn()

    {

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

    }


void principalFn(void (*ptr)())

    {

        cout<<"principal function"<<'n';

        fn();

        (*ptr)();

    }


void cb()

    {

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

    }


int main()

{

    void (*ptr)() = &cb;

    principalFn(cb);

 

   return 0;

}

Outputnya adalah:

    principal function

    seen

    callback function

Ini adalah tiruan dari perilaku asinkron. Ini bukan perilaku asinkron. Ini 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:

#include <iostream>

using namespace std;

 

void principalFn(void (*ptr)())

    {

        (*ptr)();

        cout<<"principal function"<<'n';

    }


void cb()

    {

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

    }


void fn()

    {

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

    }


int main()

{

    void (*ptr)() = &cb;

    principalFn(cb);

    fn();

 

   return 0;

}

Outputnya sekarang,

    callback function

    principal function

    seen

Ini juga merupakan tiruan dari perilaku asinkron. Ini bukan perilaku asinkron. Ini 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:

type output;

type cb(type output)

    {

        //statements

    }


type principalFn(type input, type cb(type output))

    {

        //statements

    }

Perhatikan posisi input dan output data di tempat yang berbeda dari pseudo-code. Input dari fungsi callback adalah outputnya. Parameter dari fungsi utama adalah parameter input untuk kode umum dan parameter untuk fungsi callback. 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:

#include <iostream>

using namespace std;

char *output;


void cb(char out[])

    {

        output = out;

    }

 

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

    {

        (*ptr)(input);

        cout<<"principal function"<<'n';

    }


void fn()

    {

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

    }


int main()

{

    char input[] = "callback function";

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

    principalFn(input, cb);

    fn();

    cout<<output<<'n';

 

   return 0;

}

Keluaran programnya adalah:

    principal functi
on

    seen

    callback function

Dalam kode khusus ini, datum keluaran dan masukan kebetulan merupakan 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 callback 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

Ide dari 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 tersebut. 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 sinkronisasi ():

#include <iostream>

#include <future>

#include <string>

using namespace std;

future<string> output;

string cb(string stri)

    {

        return stri;

    }

 

void principalFn(string input)

    {

        output = async(cb, input);

        cout<<"principal function"<<'n';

    }


void fn()

    {

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

    }


int main()

{

    string input = string("callback function");

    principalFn(input);

    fn();

    string ret = output.get();   //waits for callback to return if necessary

    cout<<ret<<'n';

 

   return 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, dalam 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.

Related Posts