开发者

C++ class: pointer to a non-static func

This is my last question. I try to improve my class Thread. Constructor receives pointer to the function, that must run in a new thread.

class Thread { 
    public:
     Thread(void (*p)()) {
        pf=p;
      }
     ~Thread () {}
    void StartThread() {
     hThread = (HANDLE)_beginthreadex( NULL, 0, ThreadProc, NULL, 0, &threadID); 
    }
    private: 
     void (*pf)();
     HANDLE hThread; 
     unsigned threadID;
     static unsigned WINAPI ThreadProc(LPVOID lpParam) {
      (*pf)(); //error C2597 illegal reference to non-static member
      return 0; 
     }
    }; 

In ThreadProc I need to call TimerFunc.

void TimerFunc () {
    i++;
}

Example of usage this class:

Thread *timer; 
timer = new Thread(TimerFunc);  
timer->StartThread();

So it doesn't work. Please somebody tell me, if this class is foolish. May be it is a bad idea to send pointer to func which is situated outside class?? Thank you.

Thanks very much for your advices! Now it works!

class Thread { 
public:
    Thread(void (*p)()) {
        gg.pf=p;
    }
    ~Thread ();
    void StartThread() {
     hThread = (HANDLE)_beginthreadex( NULL, 0, ThreadProc, this, 0, &threadID); 
    }
private: 
    struct mm {
        Thread *pThread; 
        void (*pf)();
  开发者_如何学编程  } gg;
    HANDLE hThread; 
    unsigned threadID; 
    static unsigned WINAPI ThreadProc(LPVOID lpParam) {
        mm hh; 
        hh.pThread=static_cast<Thread*> (lpParam);
        hh.pf=hh.pThread->gg.pf;
        hh.pf();
        return 0; 
    }
}; 

What do you think? Is it correct choice?


As the outhers pointed out, the problem is that a static method cannot access non-static members. The usual way to do something like this is to pass the object as parameter to the thread start routine, e.g.:

class Thread { 
public:
    Thread(void (*p)()) {
        pf=p;
    }
    ~Thread () {}
    void StartThread() {
        // Pass this as argument to ThreadProc
        hThread = (HANDLE)_beginthreadex( NULL, 0, ThreadProc, this, 0, &threadID); 
    }
private: 
    void (*pf)();
    HANDLE hThread; 
    unsigned threadID;
    static unsigned WINAPI ThreadProc(LPVOID lpParam) {
        // Get the passed Thread object
        Thread *pThread = static_cast<Thread*> (lpParam);
        pThread->pf();
        return 0; 
    }
}; 


The problem is that ThreadProc is defined as static, meaning it is not bound to an object. Then, you try to use a class member that is not static and must be bound to an object.

The typical way to overcome this is to pass in a structure to your thread via a void* pointer that the creation function accepts. This structure should contain the arguments that you need to make the thing go. Somewhere in it, you should have a pointer to the class that you're trying to bind the objects to. Then, refer to pf via this pointer.


Your ThreadProc member function is a static member function. Therefore it doesn't have access to any nonstatic members or member functions, including pf. I am seeing why you decided to make TreadProc a static member function - because then you'd be able to pass it to _beginthreadex as a plain function pointer.

Well, as you see, this approach has its problems. Fixing this problem is not trivial. You can check boost thread implementation and see how they have done it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜