Function Pointer Basic

From GameDevID

Jump to: navigation, search

Author: uray

Kegunaan pointer yang utama adalah untuk menyimpan alamat memori dari sebuah variabel (data type atau object dari class). Selain menyimpan alamat dari variabel, pointer juga dapat digunakan untuk menyimpan alamat dari sebuah fungsi (function pointer).

Function pointer telah digunakan sejak dikenalkannya bahasa C,dan banyak digunakan untuk sebuah fungsi callback atau untuk meningkatkan readability dari sebuah code

Anda dapat memperlakukan function pointer seperti pointer biasa (pointer ke datatype/object), anda dapat menyimpan,mengirimkan, merubah address, atau meng-evaluasi address dari pointer ke fungsi ini dengan sifat tambahan anda dapat memanggil fungsi yang ditunjuk oleh function pointer.

Contents

Deklarasi

<type> (*<func.Name>)(<argument,..,..>);

Contoh Source Code

1  int tambah(int op1,int op2){ return op1+op2; }
2  int kurang(int op1,int op2){ return op1-op2; }
3  
4  int main(void)
5  {
6      int (*fpOperasi)(int op1,int op2);
7      fpOperasi = tambah;
8      printf("hasil panggil langsung     : %d\n",tambah(10,5));
9      printf("hasil operasi func.pointer : %d\m",fpOperasi(10,5);
10 
11     fpOperasi = kurang;
12
13     printf("hasil operasi func.pointer : %d\m",fpOperasi(10,5);
14 }

Penjelasan

baris ke-6 adalah deklarasi function pointer, yaitu pointer dengan nama fpOperasi yang menunjuk kesuatu fungsi dengan return type int dan memiliki 2 argument integer.

Baris ke-7 inisialisasi fpOperasi agar menunjuk ke fungsi tambah Baris ke-8 pemanggilan fungsi tambah secara langsung Baris ke-9 Pemanggilan fungsi tambah melalui function pointer Baris ke-11 merubah isi fpOperasi agar menunjuk ke fungsi kurang Baris ke-13 Panggil fungsi yang ditunjuk function pointer

contoh 2 (callback/error handling)


Penggunaan Function Pointer

pada contoh ini akan diperlihatkan contoh penggunakan function pointer untuk membuat sebuah mekanisme callback, pada contoh ini kita membuat sebuah fungsi pembagi dengan op1/op2, dimana kita harus mencegah op2=0

int bagi(int op1,int op2,bool (*fpTest)(int op1,int op2))
{
    if(fpTest != NULL)
    {
        if(fpTest(op1,op2) == false)return -1;        
    }
    return op1/op2;
}

bool Verifier(int op1,int op2)
{
    if(op2==0)
    {
         printf("\nerror:Operand2 berisi 0 mengakibatkan division by zero");
         return false;
    }
    if(op1 < op2)
    {
         printf("\nwarning:Operand1 < Operand2");
         return true;
    }
    else return true;	
}

int main(void)
{
    printf("a) hasil 4/2 = %d",bagi(4,2,Verifier));
    printf("b) hasil 4/0 = %d",bagi(4,0,Verifier));
    printf("c) hasil 2/4 = %d",bagi(2,4,Verifier));
    printf("d) hasil 2/4 = %d",bagi(2,4,NULL));
}

pada contoh diatas fungsi Verifier dikirimkan melalui argument dari fungsi bagi untuk digunakan sebagai verifier operand sebelum dilakukan operasi pembagian.

Bila operand dari operasi pembagian tidak valid maka fungsi verifier memberikan pesan dan me-return false agar fungsi bagi tidak melanjutkan operasi pembagian

Array pada Function Pointer


int tambah(int op1,int op2){ return op1+op2; }
int kurang(int op1,int op2){ return op1-op2; }
int kali(int op1,int op2){ return op1*op2; }
int bagi(int op1,int op2){ return op1/op2; }

int main(void)
{
    int (*fpOperasi[4])(int op1,int op2);
    
    fpOperasi[0] = tambah;
    fpOperasi[1] = kurang;
    fpOperasi[2] = kali;
    fpOperasi[3] = bagi;
    
    int op1,op2,operasi;
    printf("op1:"); scanf("%d",&op1);
    printf("op2:"); scanf("%d",&op2);
    printf("operasi:\n1.Tambah\n2.Kurang\n3.Kali\n4.Bagi\n"); 
    scanf("%d",&operasi);
    
    int hasil = fpOperasi[operasi-1](op1,op2);
    printf("operasi %d dengan op1=%d , op2=%d = %d",operasi,op1,op2,hasil);
}

Function Pointer ke Static Class Member Function

penggunaan function pointer pada C++ dibatasi, yaitu function pointer tidak boleh menunjuk pada function yang berada dalam sebuah class (class member function) kecuali function tersebut berjenis static.

class A
{
    private : 
    public  : static void WriteString(char* String);
};

void A::WriteString(char* String)
{
    printf("A::WriteString() : %s",String);
}

class B
{
    private :
    public  : void Func(void (*Writer)(char* str));
};

void B::Func(void (*Writer)(char* str))
{
    Writer("class B writing \"hello...!\"");
}

int main(void)
{
    A* a = new A;
    B* b = new B;
    
    b->Func(a->WriteString);
    
    delete a;
    delete b;
}

Namun terkadang yang menjadi masalah adalah, sebuah member function yang berjenis static, tidak memiliki akses ke member dari class, sebagai contoh bila kita rubah class A menjadi :

class A
{
    private : int privatenumber;
    public  : static void WriteString(char* String);
};

void A::WriteString(char* String)
{
    printf("A::privatenumber = %d",privatenumber);
    printf("A::WriteString() : %s",String);
}
.
.

maka compiler menyatakan error, bahwa fungsi static tidak dapat mengakses member dari class A. Namun bila kita rubah fungsi WriteString menjadi non-static (dengan menghapus keyword "static") maka fungsi WriteString tidak dapat di pass melalui argument ke B::func (karena function pointer tidak boleh menunjuk fungsi yang merupakan member class)


Function Pointer to Non-static Class Member Function

Salah satu cara agar kita dapat membuat function pointer yang menunjuk ke non-static class member function bekerja adalah dengan cara memberikan object dari class yang membernya ingin diakses

Pada masalah sebelumnya A::WriteString memerlukan akses ke private member dari A yaitu mengakses int A:rivatenumber, maka solusinya kita pass object dari class A ke argumen dari A::WriteString

kode yang sebelumnya dirubah menjadi :.

class A
{
    private : int privatenumber;
    public  : static void WriteString(char* String,A* Self);
};

void A::WriteString(char* String,A* Self)
{
    printf("A::privatenumber = %d\n",Self->privatenumber);
    printf("A::WriteString() : %s",String);
}

class B
{
    private :
    public  : void Func(void (*Writer)(char* str,A* Self),A* NeedToPass);
};

void B::Func(void (*Writer)(char* str,A* Self),A* NeedToPass)
{
    Writer("class B writing \"hello...!\"",NeedToPass);
}

int main(void)
{
    A* a = new A;
    B* b = new B;
    
    b->Func(a->WriteString,a);
    
    delete a;
    delete b;
}

Terdapat cara lain menggunakan member function pointer selain dengan cara di atas. Beberapa hal yang harus diperhatikan adalah:

1. Deklarasi Member function harus dengan menggunakan operator ::*

2. Member function pointer memerlukan objek atau pointer ke objek supaya dapat digunakan.

3. Memanggil member function pointer menggunakan operator .* atau ->* , tergantung apakah digunakan dengan objek (atau reference) atau dengan pointer. Yang menjadi masalah di sini adalah kedua operator tersebut memiliki prioritas yang lebih rendah daripada operator aplikasi fungsi, sehingga anda akan selalu memerlukan tanda kurung untuk menggunakan member function pointer.

4. Assignment ke member function pointer harus selalu menggunakan operator &. Hal ini berbeda dengan function pinter biasa dimana operator & adalah optional. Beberapa kompiler akan menerima konstruk assignment tanpa operator &, tapi itu tidak standard. Kompiler yang sesuai dengan standard C++98 akan mereject assignment member function pointer tanpa operator &.

untuk lebih jelasnya anda dapat melihat contoh program di bawah:

#include <iostream>

using std::cout;
using std::endl;

class SomeMumboJumboClass{
	int i;
public:
	void a_method();
	SomeMumboJumboClass(int p):i(p){}
};

void SomeMumboJumboClass::a_method(){
	cout << "the mumbo jumbo class has a member variable with value = "<< i<< endl;
}

typedef void (SomeMumboJumboClass::* MemberFunctionptr)() ; // ini cara mendekrarasikan typedef dari non-static member function
                                                            // this is the usual way to use member function pointer

int main(){
	SomeMumboJumboClass c(2);  // deklarasikan sebuah objek

	void (SomeMumboJumboClass::* the_mem_fun_ptr)(); // deklarasikan member function variabel bernama the_mem_fun_ptr

	the_mem_fun_ptr = &SomeMumboJumboClass::a_method; // the_mem_fun_ptr sekarang menunjuk pada SomeMumboJumboClass::a_method
													  // perhatikan operator & didepan nama function member

	c.a_method(); // pemanggilan tanpa function pointer
	(c.*the_mem_fun_ptr)(); // pemanggilan dengan function pointer

	SomeMumboJumboClass* d = new SomeMumboJumboClass(3); // ini adalah pointer ke objek
	d->a_method(); // pemanggilan normal
	(d->* the_mem_fun_ptr)(); // pemanggilan dengan pointer fungsi

	MemberFunctionptr the_mem_fun_ptr2 = &SomeMumboJumboClass::a_method; // deklarasi dan definisi member function pointer
	                                                                     // menggunakan typedef di atas. this is my preferred style.
	(c.* the_mem_fun_ptr2)(); // bisa digunakan seperti ini
	(d->* the_mem_fun_ptr2) (); // atau seperti ini

	delete d;

}

yah begitulah kira-kira... article ini hanya sebagai langkah awal saja bagi yang belum mengetahui function pointer, asalnya artikelnya mau sampai pembuatan functor, callback implementation, virtual function problem dan lain-lain..

Personal tools