Класс C ++: указатель на нестатическую функцию - PullRequest
3 голосов
/ 21 сентября 2011

Это мой последний вопрос .Я пытаюсь улучшить свой класс Тема.Конструктор получает указатель на функцию, которая должна выполняться в новом потоке.

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; 
     }
    }; 

В ThreadProc мне нужно вызвать TimerFunc.

void TimerFunc () {
    i++;
}

Пример использования этого класса:

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

Так что это не работает.Пожалуйста, кто-нибудь, скажите мне, если этот класс глуп.Может быть, это плохая идея отправить указатель на func, который находится вне класса?Спасибо.

Большое спасибо за советы!Теперь это работает!

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; 
    }
}; 

Как вы думаете?Это правильный выбор?

Ответы [ 3 ]

3 голосов
/ 21 сентября 2011

Как отметили сторонники, проблема в том, что статический метод не может получить доступ к нестатическим элементам. Обычный способ сделать что-то вроде этого - передать объект в качестве параметра в процедуру запуска потока, например ::10000

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; 
    }
}; 
2 голосов
/ 21 сентября 2011

Проблема в том, что ThreadProc определен как статический, то есть он не связан с объектом.Затем вы пытаетесь использовать член класса, который не является статическим и должен быть привязан к объекту.

Типичный способ преодолеть это - передать структуру в ваш поток через указатель void *, который создаетфункция принимает.Эта структура должна содержать аргументы, которые вам нужны, чтобы все пошло как надо.Где-то в нем должен быть указатель на класс, с которым вы пытаетесь связать объекты.Затем обратитесь к pf через этот указатель.

1 голос
/ 21 сентября 2011

Ваша ThreadProc функция-член является статической функцией-членом.Поэтому он не имеет доступа ни к каким нестатическим элементам или функциям-элементам, включая pf.Я понимаю, почему вы решили сделать TreadProc статической функцией-членом - потому что тогда вы сможете передать ее в _beginthreadex в качестве простого указателя на функцию.

Ну, как вы видите, у этого подхода есть свои проблемы.Исправление этой проблемы не тривиально.Вы можете проверить реализацию boost thread и посмотреть, как они это сделали.

...