Method pointers as arguments

Discussion in 'Mac Programming' started by Duke Leto, Jul 30, 2009.

  1. macrumors regular

    Joined:
    Mar 17, 2008
    #1
    As discussed before, I started making my own view class for GLUT, and I made an event handling method that checks for hit rectangles and calls the appropriate method that was passed.

    The method looks like this:
    Code:
    void View::mouseEvent(int x, int y, int button, void (View::*mfunc)(int, int, int))
    {
    	if(pointHitsView(x, y)) (this->*mfunc)(x, y, button);
    	
    	Enumerator* myEnum = subviews->getEnumerator();
    	if(myEnum != NULL)
    	{
    		View* nextView = (View *)myEnum->getCurrentObject();
    		while(nextView != NULL)
    		{
    			// check hit rect for subview
    			if(nextView->pointHitsView(x,y)) (nextView->*mfunc)(x, y, button);
    			nextView = (View *)myEnum->nextObject();
    		}
    	}
    }
    
    The function compiles with no errors, but when I actually use it, there is one error.
    Code:
    void mouse(int button, int state, int x, int y)
    {
    	void (View::*eventFunc)(int, int, int) = mouseDownAtPosition;
    // this gives me "mouseDownAtPosition was not declared in scope"
    	outerBox->mouseEvent(x, y, button, eventFunc);
    	testCell->mouseEvent(x, y, button, eventFunc);
    }
    
    The mouse() function is in the main.cpp, which handles drawing, and GLUT events.

    The mouseEvent() method is in View.cpp.

    Why am I getting this error?
     
  2. macrumors regular

    Joined:
    Oct 13, 2008
    Location:
    Achewood, CA
    #2
    Looks like
    Code:
    void (View::*eventFunc)(int, int, int) = mouseDownAtPosition;
    should be
    Code:
    void (View::*eventFunc)(int, int, int) = &View::mouseDownAtPosition;
    Though... do you really need method pointers for this? Couldn't you just require each View subclass to override a method called mouseDown?

    Code:
    void View::mouseEvent(int x, int y, int button)
    {
    	if(pointHitsView(x, y)) mouseDown(x, y, button);
    	
    	Enumerator* myEnum = subviews->getEnumerator();
    	if(myEnum != NULL)
    	{
    		View* nextView = (View *)myEnum->getCurrentObject();
    		while(nextView != NULL)
    		{
    			// check hit rect for subview
    			if(nextView->pointHitsView(x,y)) nextView->mouseDown(x, y, button);
    			nextView = (View *)myEnum->nextObject();
    		}
    	}
    }
    
    Also note that there's a bug in that method; it only works with a single level of nested views. (i.e. it will fail if you try to click on a subview of a subview of a subview.) You'll need to recursively descend the view hierarchy.
     
  3. macrumors 6502a

    Joined:
    Sep 17, 2007
    #3
    Are you sure you want to be using pointers to (non-static) member functions? This is a hairy subject and is not as simple as using pointers to C functions. I recommend not doing it.
     
  4. thread starter macrumors regular

    Joined:
    Mar 17, 2008
    #4
    Thanks for the bug notice!

    It works now.
     

Share This Page