Thread: Pointer to member function as callback function

  1. #1
    Registered User
    Join Date
    Feb 2002
    Posts
    114

    Post Pointer to member function as callback function

    Hello

    Let me define the problem:

    You have a class with a function that enumerates elements in a list. For each object the function calls the supplied callback function:

    Code:
    void CMyClass::EnumObjects(void (*EnumObjectCallback)(OBJECT))
    {
        for each object in the objects list{
            EnumObjectCallback(object);
        }
    }
    Now, this would work great for a case where the callbackfunction wouldn't be in a class

    Code:
    void PrintObject(OBJECT);
    -----
    pMyClass->EnumObjects(&PrintObject);
    But when the callback function is in another class, there will be problem.
    Code:
    void CAnotherClass:rintObject(OBJECT);
    -----
    pMyClass->EnumObjects(&pAnotherClass->PrintObject);
    This is where the problem is. Since I wont be knowing the classtype of the class I cant define the enum finction as EnumObjects(void(CAnotherClass::*EnumObjectCallbac k)(OBJECT)) that would otherwise be an solution. But then I could liklewise write EnumObjects(CAnotherClass *pAnotherClass), and this would beat the purpose of the callback.

    So the question is:
    How do I use pointer to member function as callback functions?

    Note that this is NOT a question about STL, since most experienced programmers out there will see that the EnumObjects function does exactly the same thing as std::for_each algo. You don't need to point that out! BTW the for_each algo even have the same callback problem! Also, it is not a question about linked lists and containers, unless your super linked list solves the problem!

  2. #2
    Registered User
    Join Date
    Feb 2002
    Posts
    114
    Nobody knows??

  3. #3
    Registered User
    Join Date
    Aug 2001
    Posts
    72
    Hi ninebit,

    in order to invoke a member function of an instance of a class you will need a pointer to that member function and a pointer (or a reference) to the right instance. If you are a bit cofused I'll give you an example:
    Code:
    class Object{
    public:
    	void ouch();
    };
    
    void Object::ouch()
    {
    	cout << "ouch";
    }
    
    class B
    {
    public:
    	void first(Object* o)
    	{
    		o->ouch();
    	}
    	void second(Object* o)
    	{
    		o->ouch(); cout << "second";
    	}
    };
    class A
    {
    public:
    	Object o1;
    	Object o2;
    
    	typedef void (*externalfunc)(Object*);
    	void enumobj(externalfunc func)
    	{
    		func(&o1);
    		func(&o2);
    	}
    
    	typedef void (B::*member_of_B_func)(Object*);
    	void enumobjB(B*instanceB, member_of_B_func func)
    	{
    		(instanceB->*func)(&o1);
    		(instanceB->*func)(&o2);
    	}
    };
    so you can easily use something similar to:
    Code:
    	A a;
    	B b;
    	a.enumobjB(&b, B::first);
    	a.enumobjB(&b, B::second);
    the tricky moment here is the use of the operator
    '->*' or '.*'

    damyan

  4. #4
    Registered User
    Join Date
    Feb 2002
    Posts
    114
    So there really isn't a way to use pointer to member functions directly without knowing at design time which class to use... I'm amazed that a OOP language can't do this... Or does OOP really mean "do not use that! its old!"?

    Well actually there is another OOP solution: templates.

    By templateate(?) what you did there in the code, i can get a step closer.

    Thanx for the help mate! Happy coding!

  5. #5
    Registered User
    Join Date
    Aug 2001
    Posts
    72
    Yes. The templates are the solution.
    Here is one possible implementation of the above example using a template member function:
    Code:
    	template <class T>
    	void enumobj(T* pInstance_of_T, void (T::*member_func_of_T)(Object*))
    	{
    		(pInstance_of_T->*member_func_of_T)(&o1);
    		(pInstance_of_T->*member_func_of_T)(&o2);
    	}
    damyan

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    What you want are template functors. It's a bit to extensive to describe here, but a search on google for Template Functors will give you several pages on that topic.

    -Prelude
    My best code is written with the delete key.

  7. #7
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    Please don't bump your own threads. It is against the rules and may result in your thread being deleted.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  8. #8
    Registered User
    Join Date
    Feb 2002
    Posts
    114
    What does bumping own thread mean?


    I'll look into template functors! Thanx for the help!

  9. #9
    Registered User
    Join Date
    Aug 2001
    Posts
    41
    There is a way to do this. But it's a bit complicated. (well not really, rather far fetched)

    here goes:

    the callback function in the class should be declared static. This is because normal functions also have to know which class there in (this variable). But static functions do not. Then if you still want to be able to acces data in the calling class, you have to give an extra parameter: the this var of the class.

    So you'll have something like this:
    Code:
    void callEnum(void (*fnc)(void *, int), void * user)
    {
      for (int i=0; i<10; i++)
      {
        (*fnc)(user, i);
      }
    }
    
    class callBack
    {
      static void fnc(void *, int);
      void fncThis(int);
      void enum();
    };
    
    void callBack::fnc(void * pntr, int val)
    {
      ((callBack *)pntr)->fncThis(val);
    }
    
    void callBack::fncThis(int val)
    {
      printf("%i\n", val);
    }
    
    void callBack::enumFnc()
    {
      callEnum(fnc, this);
    }
    call callBack.enumFnc() to print 0 to 9.


    HtH.

    Joren

  10. #10
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    >>> What does bumping own thread mean?

    http://www.cprogramming.com/cboard/a...p?s=&forumid=3
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  11. #11
    Registered User
    Join Date
    Aug 2001
    Posts
    101
    Actually, it's quite simple:
    Code:
    #include <iostream>
    #include <functional>
    
    using namespace std;
    
    template<typename Fun>
    void Enum(Fun fun) {
        // You can do here some compile-time check to see if fun has an int argument
        for(int i = 0; i < 10; ++i) fun(i);
    }
    
    struct somestruct {
        void print(int i) { cout << "somestruct::print " << i << '\n'; }
    };
    
    void print(int i) {
        cout << "print " << i << '\n';
    }
    
    int main() {
        somestruct s;
        Enum(bind1st(mem_fun(&somestruct::print), &s));
        Enum(&print);
    }
    - lmov

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 04-22-2008, 12:07 PM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. Pointer to a Member Function
    By TheDan in forum C++ Programming
    Replies: 25
    Last Post: 04-03-2006, 08:18 PM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Is it possible to have callback function as a class member?
    By Aidman in forum Windows Programming
    Replies: 11
    Last Post: 08-01-2003, 11:45 AM