Function Pointers in Classes

Started by
9 comments, last by The_Apocalypse 18 years, 1 month ago
Hi everybody, I just want to add a function pointer to a class of mine that points to a function in that class.
typedef void (__thiscall* MyFuncType)(void);
class CObject
{
public:
  MyFuncType MyFunc;

  // variables
  ...

  // constructor/destructor
  CObject()
  {
    ...

    MyFunc = (MyFuncType)&CObject::TheFunction; // i tried MyFunc = (MyFuncType)TheFunction; same result!
  }
  ~CObject() {}

  // functions
  void TheFunction(void);
};
but it keeps giving me the following error: "cannot convert from 'void (__thiscall CObject::*)(void)' to void (__thiscall *)(void)'" so i changed the typedef as follows: typedef void (__thiscall CObject::*MyFuncType)(void); now it works in the constructor, but when i try to use MyFunc, i get the following error: "term does not evaluate to a function taking 0 arguments" (this didn't happen when the typedef was like in the first place, but in that way i couldn't set the function pointer to point at my function!) Please help, I'm really stuck! [depressed] BTW: I use Visual Studio 2005 BTW2: i can't use my computer with the compiler (i use my laptop now) for at least four days, so i can't test your solutions to see if they work... but any suggestions are welcome... please...[crying]
Apocalypse, the End of the World!
Advertisement
There are two ways to implement function pointers in C++. The first is the C style function pointer. To use this method, the member function in the class needs to be declared as static and the implementation of the function cannot access non-static members/methods within the class. The second (and new in C++) is to use member function pointers. To call a function via a member function pointer, you need an instance of the class to call the function with (it will become the this pointer in the function).

If you can detail the way the function pointer is to be used then someone can suggest which method to use.

Skizz
As mentioned, it depends on how you intend to use the function pointer. If you can spare it, just make it a static function and use C style function pointers (which is actually how you have it declared there). Otherwise, you might want to look into a lightweight functor class to wrap up the class instance with the function pointer. I wrote a simple functor for a one parameter function a while back:

#ifndef EVENT_H#define EVENT_H// T is object type, U is the parameter typetemplate <class T, class U>class Event  {public:   Event(T* objPtr, void (T::*fPtr) (const U)) {_objPtr = objPtr; _fPtr = fPtr;};   void operator()(const U param) {(*_objPtr.*_fPtr)(param);}   void Call(const U param) {(*_objPtr.*_fPtr)(param);}private:   T* _objPtr;   void(T::*_fPtr)(const U);};#endif
struct Foo;typedef void (Foo::*func_type)();struct Foo{   func_type func;   void bar();   Foo();};Foo::Foo() : func(&Foo::bar) {}void bar() {}int main(){   Foo f;   (f.*(f.func))();}
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I'm trying to use the function in a function of a Class. (so I can't declare it static, because it depends on instances)

void CObject::SomeFunction(){  // do some stuff  ...  MyFunc(); // it gives me 'term does not evaluate to a function taking 0 arguments'}


thanks though!

EDIT: i just realized from your source codes that (MAYBE) i must place an asterisk before the function name when I call it? something like: *MyFunc(); ?
Apocalypse, the End of the World!
That's because MyFunc is not a function pointer. It's a member function pointer. They are not used the same way.

FunctionPointer();

(Object.*MemberFunctionPointer)();

(ObjectPointer->*MemberFunctionPointer)();
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thanks!!! I get a feeling it will work![wink]
Apocalypse, the End of the World!
Another question,

can I set up my function pointer in a 'child' class to point to a function in this 'child' class?

class CObject2 : public CObject{  CObject2()  {    MyFunc = (MyFuncType)&CObject2::SomeFunction;  }  ~CObject2() {}  void SomeFunction();};


does it work? or it will give me an error that MyFunc is of type void (__thiscall CObject::*)(void) instead of void (__thiscall CObject2::*)(void)? if yes, how can this be solved? (i mean: if you have a CObject instance (obj), the function that calls MyFunc will call obj.TheFunction, but if you have a CObject2 instance (obj2), the same function that calls MyFunc (defined in CObject, not CObject2) will call obj2.SomeFunction)

thanks

EDIT: here's a complete example if you don't understand:

cobject.h
typedef void (__thiscall* MyFuncType)(void);class CObject{public:  MyFuncType MyFunc;  // constructor/destructor  CObject()  {    MyFunc = (MyFuncType)&CObject::TheFunction;  }  ~CObject() {}  // functions  void CallingFunction(void);  void TheFunction(void);};class CObject2 : public CObject{public:  CObject2()  {    MyFunc = (MyFuncType)&CObject2::SomeFunction;  }  ~CObject2() {}  void SomeFunction(void);};


cobject.cpp
void CObject::CallingFunction(void){  *MyFunc();}void CObject::TheFunction(void) {}void CObject2::SomeFunction(void) {}


main.cpp
void main(){  CObject obj;  CObject2 obj2;  obj.CallingFunction();  // I want this to call obj.TheFunction  obj2.CallingFunction(); // and this obj2.SomeFunction}


EDIT2: I just saw your reply... thanks for the tip, but I really don't know how to use boost. (I'll learn soon, though!). anyway, thanks!!![smile]
Apocalypse, the End of the World!
boost::function and boost::bind make all of your troubles go away
Quote:Original post by The_Apocalypse
can I set up my function pointer in a 'child' class to point to a function in this 'child' class?


No. Only the other way around.

You can set a Derived::* to point to a base class member, but not a Base::* point to a derived class member. Otherwise, it would allow you to do this:

struct Foo{   int i;};struct Bar{   int j;};int Foo::*ptr = &Bar::j;  // illegal, can't convert int Bar::* to int Foo::*Foo f;(f.*ptr) = 42;            // oops! f doesn't have a j member.


It is the opposite from the 'usual' polymorphism rules.

Boost does indeed make a lot of your troubles go away :)
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan

This topic is closed to new replies.

Advertisement