Does functional pointers support non-instance types in C ++
I am trying to figure out how to use function pointers to map a method from instances in C ++ like delegates in C #.
class FunctionalPointers
{
public:
static int IncrementCounter ( int *a, int b )
{
return *a += b;
}
int NonStaticIncrementCounter ( int *a, int b )
{
return *a += b;
}
};
//Declare a functional pointer as a separate type.
typedef int ( *AFunctionalPointer ) ( int*, int );
int _tmain(int argc, _TCHAR* argv[])
{
int a = 10;
int *ptr = &a;
*ptr = 200;
//This works as the methods are static
AFunctionalPointer funcInstance = FunctionalPointers::IncrementCounter;
int result = funcInstance( ptr, a );
//But if I try to make the same call from an
//instance of a non static method I get an error. Why ?
FunctionalPointers *functionalPointer = new FunctionalPointers();
//ERROR : Compiler says it illegal operation.
AFunctionalPointer funcClassInstanceType = *functionalPointer->IncrementCounter;
int instanceResult = funcClassInstanceType( ptr, a );
return 0;
}
As you can see above, if a static method is assigned to a function pointer, it compiles fine, but if I try to do the same with a non-stationary method on an instance of the class, then the compiler throws an illegal operation error.
Mapping an instance method to a delegate in C # is very possible as snippet below
class Program
{
static void Main( string[] args )
{
int a = 200;
int b = a;
FunctionalPointer funcInstance = new FunctionalPointer();
AFunctionalPointer degegateInstance = funcInstance.Increment;
int result = degegateInstance( 200, 200 );
}
}
public delegate int AFunctionalPointer( int a, int b );
class FunctionalPointer
{
public int Increment ( int a, int b )
{
return a += b;
}
public int Decrement( int a, int b )
{
return a -= b;
}
}
My question is:
Is this a knowledge gap on my part, or is it part of a C ++ rule for defining function pointers in a different way of supporting instance types.
source to share
Pointer elements use different syntaxes. Here's your code modified to use it:
typedef int ( *AFunctionalPointer ) ( int*, int );
// Use this syntax to declare pointers to member functions
typedef int (FunctionalPointers::*InstFunctionalPointer) ( int*, int );
int main()
{
int a = 10;
int *ptr = &a;
*ptr = 200;
//This works as the methods are static
AFunctionalPointer funcStatic = FunctionalPointers::IncrementCounter;
int result = funcStatic( ptr, a );
InstFunctionalPointer funcInstance = FunctionalPointers::NonStaticIncrementCounter;
//Now when I try to make the same call from an
//instance of a non static method I don't get an error.
FunctionalPointers *functionalPointer = new FunctionalPointers();
// Use this syntax to call member functions through a member pointer
int instanceResult = (functionalPointer->*funcInstance)(ptr, a );
return 0;
}
source to share
C ++ requires different types of pointers for member functions. The C ++ FAQ contains an entire section .
You can get C # -like behavior using the std :: function wrapper from C ++ 11.
source to share
You cannot use a function pointer as a stateful delegate; instead, you need a class that overloads the function call operator()
. It can be called a function and also contain state such as the specific object on which the member function is being called.
In C ++ 11, one option is std::function
:
typedef std::function<int(int*,int)> delegate;
using namespace std::placeholders;
FunctionalPointers fp; // no need for "new" here
delegate d = [&](int * p, int a){fp.IncrementCounter(p,a);};
int result = d(ptr, a);
In C ++ 03, you can use boost::function
and boost::bind
to achieve the same, or write your own line-overloaded class operator()
:
class Delegate {
public:
typedef int FunctionalPointers::*member_fn(int*,int);
Delegate(FunctionalPointers * fp, member_fn fn) : fp(fp), fn(fn) {}
int operator()(int * p, int a) {return (fp->*fn)(p,a);}
private:
FunctionalPointers * fp; // Object to call member function of
member_fn fn; // Member function to call
};
FunctionalPointers fp;
Delegate d(&fp, &FunctionalPointers::IncrementCounter);
int result = d(ptr, a);
although you need a little more work to get polymorphic behavior or std::function
.
source to share
Pointers to static member functions are essentially the same as function pointers. On the other hand, pointers to non-static member functions are completely different beasts because they need an object for which that member function is called.
a C # expression funcInstance.Increment
binds an object to a member function and returns what you might call a normal function. C ++ equivalent:
#include <functional>
using namespace std::placeholders;
int main()
{
int a = 10;
int *ptr = &a;
*ptr = 200;
FunctionalPointers functionalPointer;
auto funcClassInstanceType = std::bind(
&FunctionalPointers::NonStaticIncrementCounter, functionalPointer, _1, _2);
int instanceResult = funcClassInstanceType( ptr, a );
}
source to share
Non-static methods are of a different type. And there is a good reason for this: they have to act on a class example! You can declare a pointer to a non-static method as such
int (FunctionalPointers::*pointer_to_non_static_method)(int*, int)
= FunctionalPointers::NonStaticIncrementCounter;
But for this you need an object!
Another option is to overload operator()
in your class:
class FunctionalPointers {
...
int operator()(int* a, int b) { return *a += b; };
...
}
and you still need an object to use it:
FunctionalPointers f;
f(a,b);
source to share