Thursday, February 1, 2007

Function Pointers and Functors in C++ [in 5 minutes]

Function pointers are very useful technique to provide late binding, to prevent switching and to implement callbacks in C/C++. Here are some example cases of C/C++ function pointers and C++ functors which can be used to eliminate switches inside your code. (Remember the design principle? The code should be closed to modification but open to extension!)

Here's the C style of doing it:


#include <stdio.h>

/* calculate2, calcualte2, etc are functions
with the same prototype */
int calculate1(int val)
{
return val*val;
}

int calculate2(int val)
{
return val+val;
}

/* passing a function pointer */
int useCalculate(int (*fnPtr)(int), int someVal)
{
return fnPtr(someVal);
}

/* using the function which takes a function pointer */
int main()
{
printf("Using calculate1 = %d\n",
useCalculate(calculate1, 10));
printf("Using calculate2 = %d\n",
useCalculate(calculate2, 10));
return 0;
}


Here's the C++ style of doing it (with method pointers):

#include <iostream>

using namespace std;

//calcualte1, calculate2 are methods with the same prototype
class Util
{
public:
int calculate1(int val)
{
return val*val;
}
int calculate2(int val)
{
return val+val;
}
};

//the above prototype is taken as a formal argument here
class UseUtil
{
Util utilObj;

public:
int useCalculate(int (Util::*methodPtr)(int), int someVal)
{
return (utilObj.*methodPtr)(someVal);
}

};

//using the method with method pointer argument
int main()
{
UseUtil useUtilObj;
cout << "Using Calculate1 = " <<
useUtilObj.useCalculate(&Util::calculate1, 10) << "\n";
cout << "Using Calculate2 = " <<
useUtilObj.useCalculate(&Util::calculate2, 10) << "\n";
return 0;
}


Here's the C++ style of doing it again (but with functors!):

#include <iostream>
using namespace std;

//it takes a "stateless functor class"
template
class UseUtil
{
public:
int useCalculate(UtilFunctor calculate, int someVal)
{
return calculate.operator()(someVal);
}

};

//out of line way
//int UseUtil::useCalculate(
// UtilFunctor calculate, int someVal)
//{
// return calculate(someVal);
//}

//first functor class
class Cal1
{
public:
int operator()(int val)
{
return val*val;
};
};

//second functor class
class Cal2
{
public:
int operator()(int val)
{
return val+val;
}
};

int main()
{
UseUtil useUtilObj1;
Cal1 calObj1;
cout << "Using Cal1 = " <<
useUtilObj1.useCalculate(calObj1, 10) << "\n";
UseUtil useUtilObj2;
Cal2 calObj2;
cout << "Using Cal2 = " <<
useUtilObj2.useCalculate(calObj2, 10) << "\n";
return 0;
}

1 comment:

Clark said...

Thanks for posting your code. I couldn't get the original code to compile, but I did a few fixes, and it compiles. I gave you credit and posted the code here