Monday, January 24, 2011

Function Pointer and It's Implementation in C/C++






Function Pointer is a pointer variable, which points to the address of a function. You must keep in mind, that a running program gets a certain space in the main-memory. Both, the executable compiled program code and the used variables, are put inside this memory.

Function Pointer provides some extremely interesting, efficient and elegant programming techniques. You can use them to replace switch/if-statements, to realize your own late-binding or to implement callbacks.

Important Note:- A function pointer always points to a function with a specific signature! Thus all functions, you want to use with the same function pointer, must have the same parameters and return-type!

Example:- How to Replace a Switch-Statement by simple function pointer


// one of these functions is selected at runtime with a swicth or a function pointer
float fPlus (float a, float b) { return a+b; }
float fMinus (float a, float b) { return a-b; }
float fMultiply (float a, float b) { return a*b; }
float fDivide (float a, float b) { return a/b; }



// solution with a function pointer - pt2Func argument is a function pointer and points to a function which takes two floats and returns a float.

void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
float result = pt2Func(a, b); // call using function pointer

cout << "switch replaced by function pointer: 2-5="; // display result cout << result << endl; } // execute example code void Replace_A_Switch() { cout << endl << "Executing function 'Replace_A_Switch'" << endl; Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus); } Define a Function Pointer in C and C++ :-

In the C++ example it is assumed, that the function, our pointer points to, is a member function of TMyClass.

int (*pt2Function) (float, char, char); // C Declaration
int (TMyClass::*pt2Member)(float, char, char); // C+ Declaration

Assign an address to a Function Pointer :-

It's optional to use the address operator & in front of the function's name. Note: You may have got to use the complete name of the member function including class-name and scope-operator (::). Also got to ensure, that it is allowed to access the function right in scope where your assignment stands.

// C Style

int DoIt (float a, char b, char c){ cout << "DoIt" << endl; return a+b+c; } int DoMore(float a, char b, char c){ cout << "DoMore" << endl; return a-b+c; } pt2Function = DoMore; // assignment pt2Function = &DoIt; // alternative using address operator // C++ Style class TMyClass { public: int DoIt (float a, char b, char c){ cout << "TMyClass::DoIt" << endl; return a+b+c; }; int DoMore(float a, char b, char c){ cout << "TMyClass::DoMore" << endl; return a-b+c; }; /* more of TMyClass */ }; pt2Member = TMyClass::DoIt; // assignment pt2Member = &TMyClass::DoMore; // alternative using address operator Comparing Function Pointers :-

// C Style

if(pt2Function == &DoIt)
cout << "pointer points to DoIt" << endl; // C++ Style if(pt2Member == &TMyClass::DoMore) cout << "pointer points to TMyClass::DoMore" << endl; Calling a Function using a Function Pointer :-

In C :

1) Use the name of the function pointer instead of the name of the function.
2) Use explicitly dereference.

In C++:-

1) Need to have an instance of a class to call one of their (non-static) member functions. If the call takes place within another member function you can use the this-pointer.

int result1 = pt2Function (12, 'a', 'b'); // C short way
int result2 = (*pt2Function) (12, 'a', 'b'); // C

TMyClass instance;
int result3 = (instance.*pt2Member)(12, 'a', 'b'); // C++
int result4 = (*this.*pt2Member)(12, 'a', 'b'); // C++ if this-pointer can be used


Pass a Function Pointer as an Argument :-

// pt2Func is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
{
float result = pt2Func(12, 'a', 'b'); // call using function pointer

cout << result << endl; } // execute example code void Pass_A_Function_Pointer() { cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl; PassPtr(&DoIt); } Return a Function Pointer :-

It's a little bit tricky but a function pointer can be a function's return value. In the following example there are two solutions of how to return a pointer to a function which is taking a float and returns two float. If you want to return a pointer to a member function you have just got to change the definitions/declarations of all function pointers.

// Simple direct solution in C

// function takes a char and returns a pointer to a function which is taking two
// floats and returns a float. specifies which function(i.e Plus() or Minus()) to return
float (*GetPtr1(const char opCode))(float, float)
{
if(opCode == '+') return &Plus;
if(opCode == '-') return &Minus;
}


// solution using a typedef

// define a pointer to a function which is taking two floats and returns a float
typedef float(*pt2Func)(float, float);

// function takes a char and returns a function pointer which is defined as a
// type above. specifies which function to return
pt2Func GetPtr2(const char opCode)
{
if(opCode == '+') return &Plus;
if(opCode == '-') return &Minus;
}


// execute example code
void Return_A_Function_Pointer()
{
cout << endl << "Executing 'Return_A_Function_Pointer'" << endl; float (*pt2Function)(float, float); // define a function pointer pt2Function=GetPtr1('+'); // get function pointer from function 'GetPtr1' cout << pt2Function(2, 4) << endl; // call function using the pointer pt2Function=GetPtr2('-'); // get function pointer from function 'GetPtr2' cout << pt2Function(2, 4) << endl; // call function using the pointer } Use Arrays of Function Pointers :-

Operating with arrays of function pointers is very interesting. This offers the possibility to select a function using an index. The syntax appears difficult, which frequently leads to confusion.

// C
// type-definition: 'pt2Function' now can be used as type
typedef int (*pt2Function)(float, char, char);

// illustrate how to work with an array of function pointers
void Array_Of_Function_Pointers()
{
cout << endl << "Executing 'Array_Of_Function_Pointers'" << endl; // is an array with 10 pointers to functions which return an int
// and take a float and two char
pt2Function funcArr[10];

funcArr[0] = &DoIt;
funcArr[1] = &DoMore;
/* more assignments */

// calling a function using an index to address the function pointer
cout << funcArr[1](12, 'a', 'b') << endl; cout << funcArr[0](12, 'a', 'b') << endl; } // C++ // type-definition: 'pt2Member' now can be used as type typedef int (TMyClass::*pt2Member)(float, char, char); // illustrate how to work with an array of member function pointers void Array_Of_Member_Function_Pointers() { cout << endl << "Executing 'Array_Of_Member_Function_Pointers'" << endl; // is an array with 10 pointers to member functions which return an
// int and take a float and two char
pt2Member funcArr[10];

funcArr[0] = &TMyClass::DoIt;
funcArr[1] = &TMyClass::DoMore;
/* more assignments */

// calling a function using an index to address the member function pointer
// note: an instance of TMyClass is needed to call the member functions
TMyClass instance;
cout << (instance.*funcArr[1])(12, 'a', 'b') << endl; cout << (instance.*funcArr[0])(12, 'a', 'b') << endl; } In C++, one way to get late binding, which also called Dynamic binding is to use function pointers because it is not possible to know which function will be called until runtime (when the program is run). Calling a function via a function pointer is also known as an indirect function call. If you call a virtual function, your program has got to determine which one has got to be called. It does this using a V-Table containing all the possible functions. This costs some time each call and maybe you can save some time using function pointers instead of virtual functions.

No comments:

Post a Comment