28 Mayıs 2020 Perşembe

Function Pointer To Global Method

Giriş
C++ ile iki çeşit function pointer var. İlki global bir fonksiyona pointer. Bu klasik C ile aynı. İkincisi ise Function Pointer to Member Method. Yani bir sınıfın/struct'ın içinde tanımlı metoda pointer.

Function Pointer Tanımlama - C++98
Şöyle yaparız.
typedef return_type (*methodname)(const methodparameters&);
Function ismi etrafındaki parantezler gerekli! Böylece function ve function pointer ayırt edilebiliyor. Aşağıda function ve function pointer tanımlamalarının farkı görülebilir.
// not function pointers: * not grouped to function name
int x(); // function that returns an int
int* x(); // function that returns an int*
int *x(); // also a function that returns an int*, spaces don't matter

// function pointers: * grouped to function name
int (*x)(); // pointer to a function that returns an int
int* (*x)(); // pointer to a function that returns an int*
Function pointer'lar kodu okumayı ve test etmeyi zorlaştırıyor. Mümkünse kullanmamak lazım.

Örnek
Not : Bu örnekte function pointer kullanılmıyor ancak gerçek function cast edilerek kullanılıyor.

C dilinde function pointer tanımlamadan parametresiz function'a pointer kullanmak mümkün. Bu çok eski bir özellik ve ileride muhtemelen kaldırılır. Açıklaması şöyle.
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
 Şöyle yaparız
#include    <stdio.h>
#include    <stdlib.h>

typedef void    funp();

static  void    funcall( funp* F, int args, double x)
{
    switch( args)
    {
        case    0:  F();    break;
        case    1:  F(x);   break;
    }
}

static  void    fun0( void)
{
    printf( "zero\n");
}

static  void    fun1( double x)
{
    printf( "one\t%f\n", x);
}

int main( )
{
    funcall( (funp*)fun0, 0, 17.0);
    funcall( (funp*)fun1, 1, 17.0);
    return EXIT_SUCCESS;
}

Function Pointer Tanımlama - C++11
C++11 ile şöyle yaparız.
using methodname = return_type (*)(const methodparameters&);
Şöyle yaparız.
using A = int(*)(); // pointer to function returning int
using B = A(*)();  // pointer to function returning pointer to function returning int

B foo(); //function returning pointer to function
  returning pointer to function returning int
Parametre Almayan Function Pointer Array
Parametre almayan ve void dönen dizi için şöyle yaparız.
void (*arr[5])() = {
    [] { fun1(); },
    [] { fun2(); },
    [] { fun3(); },
    [] { fun4(); },
    [] { fun5(); }
};
Array yerine std::vector istersek şöyle yaparız.
std::vector<void(*)()> fvec = {
    []{ func0(); },
    []{ func1(); },
    []{ func2(); },
}
Parametre almayan bir function pointer tanımlama
Şöyle yaparız.
void fun(){cout<<"fun called";}  

typedef void (*pf)();
pf p1 = fun;
//Then we can call p1()
p1();
Çift parametre alan function pointer tanımlama
Şöyle yaparız
int subtraction(int a,int b){
    return a-b;
}


int (*minus)(int,int)=subtraction;
cout<<minus(5,4);
Function Pointer Atama
Function pointer tanımlaması yaptıktan sonra bir değişkene veya parametreye atayarak çağırmak isteriz. Function pointer çevrimi özelliğinden dolayı atama veya parametre geçme işlemini istersek & işareti, * işareti, veya bunlar olmadan da yapabiliriz.
int foo();
int (*bar)() = foo; // the compiler implicitly assigns the address of foo to bar
int (*baz)() = &foo; // you explicitly assign the address of foo to baz
şeklinde de yazabilirdik. Yani tanımlı bir function, tıpkı array'lerde olduğu gibi otomatik olarak pointer'a çevrilebiliyor.
A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type."
Function Pointer Çağırma
Çağırma da atama gibi manyakça kodlara dönüşebiliyor. Aşağıdaki kodların hepsi çalışır ve atanmış function pointer her türlü çağrılır.
#include <stdio.h>
typedef void print(void);
static void dosomething(void) { printf("Hello World\n"); }

int main(void)
{
    print *f1 = dosomething;
    print *f2 = &dosomething;
    f2();
    (f1)();
    (*f1)();
    (**f2)();
    (***f1)();
    (****f2)();
    (*****f1)();
}