Function Pointer in a class pointing out of the class

Hello I'm working on a project where I need to use a function pointer in a static class member that points to a non-member function. When I try to do this it gives me a error: invalid use of member 'Thing::fp' in static member function. Help would be much appreciated!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>

using namespace std;

void Hello()
{
    cout << "Hello" << endl;
}

typedef void (*FunctionPtr)();

class Thing
{

    public:
    FunctionPtr fp;

    Thing(void (*p)())
    {
        fp = p;
    }

    static void Start()
    {
        fp();
    }

};

int main()
{
    Thing A(&Hello);
    return 0;
}
Last edited on
fp is a simple member variable. Each object of type Thing will have a different fp associated with it. Start, however, is static and thus is not related to any specific object. Therefore it does not have a way to know what fp you want to use. The solution is either to remove static from Start or add static to fp. Note that the second option would require some more modifications.
First of all thanks for the snappy response!

I can't make Start() not static so what kind of modifications are we talking about?

I made fp static and now it gives me the error: undefined reference to `Thing::fp'|
Last edited on
Add FunctionPtr Thing::fp; after the class declaration (if you had the declaration in a header, you'd still need to put that line in a cpp file).
Remove the constructor (you can keep it, but remember that a constructor is for objects fp is for the whole class. If you do intend to create some instances, their constructors should not modify fp. It's ok to use it though). You may want to write static void init(void (*p)()) instead (although plain = will work too).
Remember that when you use a static member, it will be Thing::Start() instead of mything.Start().
The issue is I need to acess it in a static member function but it needs to be unique for each class. I need to store function pointers for each instance of the class not for every instance :)
Is it not possible to pass the function pointer as a parameter?
Remember that when you use a static member, it will be Thing::Start() instead of mything.Start().
The latter is valid as well.

I need to store function pointers for each instance of the class not for every instance :)
Did you mean store a function pointer unique to the class and not instances of the class? If so follow hamsterman's advice.
The issue is I need to acess it in a static member function but it needs to be unique for each class.


What you want and what you are doing are two opposite things.

static members exist once and all objects share the same instance of that member.

non-static members have a unique instance for all objects.

So based on what you are saying, you want unique instances. Therefore you do NOT want static. So get rid of ?all? static keywords here, as they are not what you want.
Yeah Disch I'm unsure what the OP is saying based on this...
I need to store function pointers for each instance of the class not for every instance :)
Sorry if a am unclear, the member fuction is a thread that is why it must be static
Thread callbacks often have a "user data" pointer which is just for this purpose.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MyClass
{
public:
  static void ThreadEntry(void* userdata)
  {
    MyClass* ptr = reinterpret_cast<MyClass*>(userdata);
    ptr->RunThread();
  }

  void RunThread()  // <-  note:  non-static
  {
  }
};


int main()
{
  // start a new thread, give it a pointer to the static function
  //  and also give it a pointer to a MyClass object
  MyClass obj;

  start_another_thread( &MyClass::ThreadEntry, &obj );
}


Of course exactly how you specify the userdata will vary slightly depending on the API.
Thanks so much I will try this out :)
The thing is that the Thread must be static and it must call either a function by pointer stored in the class or be able to call a non-static function that would then execute the function by pointer.

Here is my full code, I am using windows threads.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <vector>
#include <windows.h>
#include <process.h>

using namespace std;

void Hello()
{
    cout << "Hi!" << endl;
}

typedef void (*FunctionPtr)();

class Worker
{
    protected:
    HANDLE WorkerThreadHandle;
    DWORD WorkerThreadID;
    FunctionPtr FunctionCall;

    public:
    Worker( void (*Function)() )
    {
        FunctionCall = Function;
        //FunctionCall();
        _beginthread( WorkerLauncherThread, 0, (void*)Function );

    }

    static void WorkerLauncherThread(void *arg)
    {

        RunnerThreadFunction();
        //FunctionCall();
        _endthread();
    }

    void RunnerThreadFunction()
    {
        FunctionCall();
    }

    void join()
    {

    }


};

int main()
{

    vector<Worker> WorkVec;
    WorkVec.push_back(Hello);
    WorkVec.push_back(Hello);


    Sleep(1000);
    return 0;
}
Last edited on
yeah, see:

 
static void WorkerLauncherThread(void *arg)


that 'void *arg' argument is your user data. You want to pass a pointer to an object to that function. You can then use that object to call a non-static member.

1
2
3
4
5
6
    static void WorkerLauncherThread(void *arg)
    {
        Worker* ptr = reinterpret_cast<Worker*>(arg);  // cast the argument to a pointer to this class
        ptr->RunnerThreadFunction();  // <- call the non-member function using that object
        _endthread();
    }


The other part of this is passing a pointer to a valid object to _beginthread so that you get that pointer in your callback. This is what the 3rd parameter is for:

1
2
_beginthread( WorkerLauncherThread, 0, this );  // <-  pass it 'this', which is a pointer
 // to the current 'Worker' object.  That pointer will then be 'arg' in your callback function. 




Also, I DO NOT RECOMMEND using 'this' in your constructor. Starting a new thread in a class constructor is kind of a sketchy idea. Personally I would have a separate 'Start' function or something which actually fires up the new thread.
Last edited on
Thanks so much! I got it working now.
Last edited on
Topic archived. No new replies allowed.