Thread: Pointers to Class Member Functions

  1. #1
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174

    Pointers to Class Member Functions

    I am working on a class that holds a vector of class member functions. While normal function pointers a quite easy to implement I have discovered that using pointers to member functions take a bit more thought.

    My first attempt:
    Code:
    typedef void *pData;
    typedef void(*pFunction)(pData);
    class MyClass1
    {
    public:
        MyClass1() { m_a = 5; m_b = 10; }
        ~MyClass1() { }
        void Go();
        static void f1(pData d) { std::cout<<"Member Function 1.  a = " <<static_cast<MyClass1*>(d)->m_a <<"\n"; }
        static void f2(pData d) { std::cout<<"Member Function 2.  b = " <<static_cast<MyClass1*>(d)->m_b <<"\n"; }
    private:
        std::vector<pFunction> m_VecFunc;
        int                    m_a, m_b;
    };
    void MyClass1::Go()
    {
        m_VecFunc.push_back(&f1);
        m_VecFunc.push_back(&f2) ;
        std::vector<pFunction>::iterator iter;
        for (iter = m_VecFunc.begin(); iter != m_VecFunc.end(); ++iter)
        {
            (*iter)(this);
        }
        return;
    }
    This works quite well. The only problem is that in order to access member variables I have to pass this to the function and cast it to a MyClass1 pointer before each call to a member variable.
    I'm not sure I like this. While it works it seems like more work than it should be, having to remember to cast each member variable before I use it.

    So then I came up with my second approach.
    Code:
    class MyClass2
    {
    public:
        MyClass2() { m_a = 5; m_b = 10; }
        ~MyClass2() { }
        void f1() { std::cout<<"Member Function 1.  a = " <<m_a <<"\n"; }
        void f2() { std::cout<<"Member Function 2.  b = " <<m_b <<"\n"; }
        void Go();
        void DoCallBack(pFunction f, pData x) { f(x); }  // calls f(x)
    private:
        static void call_f1(pData d) { static_cast<MyClass2*>(d)->f1(); }
        static void call_f2(pData d) { static_cast<MyClass2*>(d)->f2(); }
        int                    m_a, m_b;
        std::vector<pFunction> m_VecFunc;
    };
    void MyClass2::Go()
    {
        m_VecFunc.push_back(call_f1);
        m_VecFunc.push_back(call_f2);
        std::vector<pFunction>::iterator iter;
        for (iter = m_VecFunc.begin(); iter != m_VecFunc.end(); ++iter)
        {
            (*iter)(this);
        }
        return;
    }
    This also works quite well. I no longer have to cast each member variable before I can use it. The only problem now is that for each member function I want to take the address of, I have to have a second function just to call it. And I still have to pass this to the calling function.
    I'm not sure I care for this either.

    Is there a way of doing this so that I can directly use member variables without having to do any type casting?
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    For your examples you don't have to take the detour via a static function.

    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class MyClass;
    
    typedef void (MyClass::*pt2tMember)( int );
    
    class MyClass {
    public:
        MyClass() { m_a = 5; m_b = 10; m_c = 15; }
    
        ~MyClass() { }
        void Go();
    
        void f1( int d) { 
            std::cout<<"Member Function 1.  a = " << m_a << "," << d <<"\n"; 
        }
        void f2( int  d) { 
            std::cout<<"Member Function 2.  b = " << m_b << "," << d <<"\n"; 
        }
        void f3( int  d) { 
            std::cout<<"Member Function 2.  c = " << m_c << "," << d <<"\n"; 
        }
    
    private:
        std::vector< pt2tMember > m_VecFunc;
        int  m_a, m_b, m_c;
    };
    
    void MyClass::Go()
    {
        m_VecFunc.push_back(&MyClass::f1);
        m_VecFunc.push_back(&MyClass::f2) ;
        m_VecFunc.push_back(&MyClass::f3) ;
    
        std::vector< pt2tMember >::iterator iter;
        
        int i = 0;
        for (iter = m_VecFunc.begin(); iter != m_VecFunc.end(); ++iter, ++i)
            (*this.*(*iter))( i );
        return;
    }
    
    int main() {
        MyClass a;
        a.Go();
    }
    Kurt

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    What you wish you had is a "bound function pointer." It doesn't exist natively in C++, but you can implement it using tr1::binder objects. Other people have implemented equivalent mechanisms -- for instance, see:

    http://www.tutok.sk/fastgl/callback.html

  4. #4
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    Quote Originally Posted by ZuK View Post
    For your examples you don't have to take the detour via a static function.
    The impression that I got from everything that I read was that you could not take the address of a member function unless it was static. My very first attempt seemed to confirm this as I kept getting one error that I could not resolve. I never thought of calling the function pointer through this. That is exactly what I was looking for.... Thanks!
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by ZuK View Post
    Code:
    (*this.*(*iter))( i );
    I think a better syntax is:

    Code:
    (this->*iter)( i );
    They are equivalent, of course.

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by brewbuck View Post
    Code:
    (this->*iter)( i );
    They are equivalent, of course.
    Code:
    error: no match for 'operator->*' in 'this ->* iter'
    this would work ( Calling member function pointers is a bit funny )
    Code:
    (this->*(*iter))( i );
    Kurt

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by ZuK View Post
    Code:
    error: no match for 'operator->*' in 'this ->* iter'
    this would work ( Calling member function pointers is a bit funny )
    Code:
    (this->*(*iter))( i );
    Kurt
    Oops. I didn't read the code fully. Though iter was a bare member function pointer itself

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Help with FIFO QUEUE
    By jackfraust in forum C++ Programming
    Replies: 23
    Last Post: 04-03-2009, 08:17 AM
  3. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  4. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM
  5. class member access denied
    By chiqui in forum C++ Programming
    Replies: 2
    Last Post: 05-27-2002, 02:02 PM