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.

+3


source to share


6 answers


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;
}

      

+1


source


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.

+4


source


A pointer to a class member must be declared as:

int (ClassName::*FunctionPointer)(int, int);

      

+2


source


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

.

+1


source


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 );
}

      

+1


source


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);

      

+1


source







All Articles