Sign in to follow this  

Pointer to function

This topic is 4395 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a class that has a pointer to a function as one of it's variables. I assign it to another function in the constructor, but I get a "non-lvalue in assignment" error. I know what that means, but what I want to know is this: Why isn't my value a valid pointer that can be given an address? Here is the appropriate code:
class creature
{
  creature(int whichfunc);
  int funca();
  int funcb();
  int (*func)();
}


creature::creature(int whichfunc)
{
  if (whichfunc)
  {
    (*func)() = funca;
  }
  else
  {
    (*func)() = funcb;
  }
}


One more question: how would I call that function? I'm guessing
  *func();

Share this post


Link to post
Share on other sites

class Event
{
public:
Event(){}
virtual void Call(int c)=0;
};

template <class T>
class GuiEvent : public Event
{
void (T::*m_Func)(int);
T* m_This;
int m_Flag;
public:
GuiEvent(T* l_This,void(T::*l_Func)(int),int l_Flag)
{
m_This = l_This;
m_Func = l_Func;
m_Flag = l_Flag;
}

void Call(int l_Flag)
{
if(m_This && m_Func)
{
(*m_This.*m_Func)(l_Flag);
}
}
};




http://www.newty.de/fpt/functor.html

Share this post


Link to post
Share on other sites
Member function pointers and function pointers are two different things.

What you have defined is a pointer to a function, not a pointer to a member function.


class MemFnPtrTest
{
public:
// constructor
MemFnPtrTest( int nWhich );

private:
// typedefs
typedef int (MemFnPtrTest::*FnPtr)( void );

// private member functions
int MemberFn1( );
int MemberFn2( );

void SomeFn( );

// member variables
FnPtr m_MemberFnPtr;

};

inline MemFnPtrTest::MemFnPtrTest( bool bFn1 )
{
m_MemberFnPtr = bFn1 ? &MemFnPtrTest::MemberFn1 : &MemFnPtrTest::MemberFn2;
}



To actually use the member function pointer, you have to have a reference / pointer to an object before you can execute the function.


void MemFnPtrTest::SomeFn( )
{
(this->*m_MemberFnPtr)();
}



Hope this helps.

Share this post


Link to post
Share on other sites
Of course, that fixes the right side of the assignment, but the compiler is currently too busy complaining about the left side :) When you write "int (*func)();", that declares a member whose name is "func" and whose type is "int(creature::*)()". When we assign things, we want to write the variable name, not its type (or any part of the notation therefor). Thus "(*func)()" is not what you want on the left side: that means "evaluate func, and the result of that evaluation is what I want to assign to". You can assign to an int-typed variable, but you can't assign to an int returned from a function - it's not an l-value. What you want on the left side is just "func".

That said, chances are good your real code doesn't really need and won't benefit from function pointers being used in this way. If the idea is that the creature behaves in either the funca() or the funcb() way at different times, then the simple way is to just have a data member that encodes which one to use, and code func() to do an if-check (or switch) on that data. As there get to be more cases, you may instead want to look into the Strategy pattern.

Share this post


Link to post
Share on other sites
I was actually using it to represent the ai for the creature. I hypothesize that it will become faster to use a pointer than a switch when I get about 20 different behaviors. I tdefinitely needs to be profiled both ways though.

Share this post


Link to post
Share on other sites

class creature
{
creature(int whichfunc);
int funca();
int funcb();
int (creature::*func)();
}


creature::creature(int whichfunc)
{
if (whichfunc)
{
func = &creature::funca;
}
else
{
func = &creature::funcb;
}
}

This should work (note these corrected-bold lines), though someone out there has already provided you (better ?) alternatives. Using functors and/or desired patterns as you wish, when calling these functions, simply put:
int iRet = (creature_pInstance ->* (creature_pInstance -> func)) () ;

or
 int iRet = (creature_Instance.*(creature_Instance.func)) () ;

or
 int iRet = (this ->* func) () ;
(If you're calling in it's member functions).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by NIm
I was actually using it to represent the ai for the creature. I hypothesize that it will become faster to use a pointer than a switch when I get about 20 different behaviors. I tdefinitely needs to be profiled both ways though.


Have you considered using the newfangled object-oriented methodology? Instead of pointers to functions and switch statement, you just use the keyword "virtual" in front of your member functions and the rest works like magic.

Share this post


Link to post
Share on other sites
Quote:
Original post by NIm
I was actually using it to represent the ai for the creature. I hypothesize that it will become faster to use a pointer than a switch when I get about 20 different behaviors. I tdefinitely needs to be profiled both ways though.


That's fine, but polymorphism can be used to accomplish the same thing without extra overhead and with much nicer syntax. In your case, what you'd probably do is create a polymorphic class to represent the func() process - say we have an abstract base class "CreatureBehaviour", which we then derive from. Each Creature holds a pointer to CreatureBehaviour, and delegates to it. If there is only one function that CreatureBehaviour really needs to provide (aside from construction and destruction), in C++ we can use the operator() for that instead of a named member function, in order to clean up the syntax a bit:


class CreatureBehaviour {
// whatever else is necessary
public:
virtual CreatureBehaviour* operator() (Creature& owner) = 0;
// We return a pointer to some CreatureBehaviour object so as to represent
// a change in behaviour that results from the execution - if the behaviour
// should stay the same, we can just "return this;".
}

class Creature {
CreatureBehaviour * action;
public:
void act() {
action = action(*this);
}
}


This is the Strategy pattern, specifically the Run and Return Successor variant which I have personally found most useful in the past. In C++, the main difficulty is in managing the objects - you probably should use smart pointers instead of the raw ones that are illustrated (this is something that is much easier in a GC environment).

Share this post


Link to post
Share on other sites

This topic is 4395 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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