Sign in to follow this  
freeworld

function pointers to non static member functions

Recommended Posts

I just recently started using function pointers, and now I've run into a road block. I've got a variable outside of a class that stores function pointers. but I want to include a pointer to a member function. The easiest option ofcourse is making the function static, but what if I come across a situation where I can't make it static but really want to use function pointers. Are there was around this?

Share this post


Link to post
Share on other sites
Google gave me this:

Taken from : Link

[33.2] How do I pass a pointer-to-member-function to a signal handler, X event callback, system call that starts a thread/task, etc?

Don't.

Because a member function is meaningless without an object to invoke it on, you can't do this directly (if The X Window System was rewritten in C++, it would probably pass references to objects around, not just pointers to functions; naturally the objects would embody the required function and probably a whole lot more).

As a patch for existing software, use a top-level (non-member) function as a wrapper which takes an object obtained through some other technique. Depending on the routine you're calling, this "other technique" might be trivial or might require a little work on your part. The system call that starts a thread, for example, might require you to pass a function pointer along with a void*, so you can pass the object pointer in the void*. Many real-time operating systems do something similar for the function that starts a new task. Worst case you could store the object pointer in a global variable; this might be required for Unix signal handlers (but globals are, in general, undesired). In any case, the top-level function would call the desired member function on the object.

Here's an example of the worst case (using a global). Suppose you want to call Fred::memberFn() on interrupt:


class Fred {
public:
void memberFn();
static void staticMemberFn(); // A static member function can usually handle it
...
};

// Wrapper function uses a global to remember the object:
Fred* object_which_will_handle_signal;

void Fred_memberFn_wrapper()
{
object_which_will_handle_signal->memberFn();
}

int main()
{
/* signal(SIGINT, Fred::memberFn); */ // Can NOT do this
signal(SIGINT, Fred_memberFn_wrapper); // OK
signal(SIGINT, Fred::staticMemberFn); // OK usually; see below
...
}




Note: static member functions do not require an actual object to be invoked, so pointers-to-static-member-functions are usually type-compatible with regular pointers-to-functions. However, although it probably works on most compilers, it actually would have to be an extern "C" non-member function to be correct, since "C linkage" doesn't only cover things like name mangling, but also calling conventions, which might be different between C and C++.

Don't forget to rate :)

Share this post


Link to post
Share on other sites
You could use functors instead of raw function pointers, this allows some more flexibility. For instance, with functors, you can extend functionality using polymorphism:


class Signal {
public:
virtual ~Signal() {
}

virtual void operator() () = 0;
};


class FunctionWrapper : public Signal {
private:
typedef void (*FunctionPointer)();

public:
FunctionWrapper( FunctionPointer ptr )
: mFunction( ptr ) {
}

void operator() () {
(*mFunction)();
}

private:
FunctionPointer mFunction;
};


template<class Type, class BaseType>
class BoundSignal: public Signal {
private:
typedef void (Type::*FunctionPointer)();

public:
MemberSignal( Type& obj, FunctionPointer p ) :
mTargetFunction( p ),
mTargetObject( obj )
{
}

void operator() () {
(obj.*mTargetFunction)();
}

private:
FunctionPointer mTargetFunction;
Type& mTargetObject;
};

//
// Sample:
//

class Person {
public:
Person( const string& name )
: mName( name ) {
}

void speak() {
cout << "Hello, my name is " << mName << endl;
}

private:
string mName;
};

Person Fred( "Fred" );

void sayHi() {
cout << "Hi!" << endl;
}

map<string, Signal*> theMap;
theMap["sayHi"] = new FunctionWrapper( sayHi );
theMap["abc"] = new BoundSignal<Person>( Fred, &Person::speak );

(*theMap["sayHi"])(); // "Hello, my name is Fred"
(*theMap["abc"])(); // "Hi!"

// pseudo code:
// for_each( theMap.begin(), theMap.end(), delete );



* Not tested

Alternatively, you can use boost::function in conjunction with boost::bind, or boost::signals.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this