Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Member function pointer to unspecified class type - is it possible?

Is it possible to declare a function pointer (non C++ 11) that can point to a member function of any class (read: not a specific class)?

For example, if I had class A, B, and C. C has a function pointer declared in it, and I'd like to switch that pointer between pointing to one of B's member function's and one of A's member functions. Does C++ allow this?

like image 445
John Humphreys Avatar asked Jan 17 '12 16:01

John Humphreys


People also ask

Can a pointer refer to any type?

Every pointer is of some specific type. There's a special generic pointer type void* that can point to any object type, but you have to convert a void* to some specific pointer type before you can dereference it.

Can this pointer point to another class?

It is true that a pointer of one class can point to other class, but classes must be a base and derived class, then it is possible.

Can we create a pointer to a member function?

You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.

How many different ways are possible to pass a pointer to a function call?

There are three ways to pass variables to a function – pass by value, pass by pointer and pass by reference.


1 Answers

Yes you can, but you have to remove some type safety and keep track of the this pointer as well as the member function.

You can see a use-case in http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates. The basic idea is to store the object pointer as a void pointer and redirect the function call through a static method.

#include <iostream>
using namespace std;

struct A { void foo() { cout << "A::foo\n"; } };
struct B { void foo() { cout << "B::foo\n"; } };

class C
{
public:
    C() : object_ptr(0), stub_ptr(0) {}

    template <class T, void (T::*TMethod)()>
    static C from_method(T* object_ptr)
    {
        C d;
        d.object_ptr = object_ptr;
        d.stub_ptr = &method_stub<T, TMethod>;
        return d;
    }

    void operator()() const
    {
        return (*stub_ptr)(object_ptr);
    }

private:
    typedef void (*stub_type)(void* object_ptr);

    void* object_ptr;
    stub_type stub_ptr;

    template <class T, void (T::*TMethod)()>
    static void method_stub(void* object_ptr)
    {
        T* p = static_cast<T*>(object_ptr);
        return (p->*TMethod)();
    }
};

int main() 
{
    A a;
    B b;

    C c = C::from_method<A, &A::foo>(&a);

    c();

    c = C::from_method<B, &B::foo>(&b);

    c();

    return 0;
}

The code above should print

A::foo
B::foo

This solution is faster than using std::function since it doesn't require a heap allocated storage for the data but this may only be used to reference member functions (unlike std::function that claims ownership of any callable object).

like image 133
Jens Åkerblom Avatar answered Sep 22 '22 09:09

Jens Åkerblom