2011-01-12 3 views
5

Как говорится в названии. Следующий мой скелет кода.запустить потоки функции члена класса в C++

class CLASS 
{ 
public: 
    void A(); 
private: 
    DWORD WINAPI B(LPVOID); 
}; 

void CLASS::A() 
{ 
    DWORD (WINAPI CLASS::*thread)(LPVOID) = &CLASS::B; 
    ... 
    CreateThread(NULL, 0, thread, &arg, 0, NULL); 
    ... 
} 

Функция B требует переменных члена CLASS.
Но у меня есть код ошибки, когда я скомпилировал это.
Это «не может преобразовать аргумент 3 из« DWORD (__stdcall CLASS :: *) (LPVOID) »в« LPTHREAD_START_ROUTINE »или что-то в этом роде.
Я не знаю, совпадает ли это с английской средой.

Может кто-нибудь помочь пожалуйста?

ответ

3

Вы должны сделать эту функцию static.

Проблема заключается в том, что каждая нестатическая функция-член имеет неявный параметр this, и это на самом деле то, что компилятор пытается рассказать вам: ваша функция-член-член-член имеет отличную от той, которую вы ожидали.

См. Также this answer to a closely related question.

+3

И перед началом О.П. получение любых умных идей - нестатические указатели на функции членов класса * странные *. Не только вызывающие соглашения отличаются от простого 'func (classname * this, ...)', представление _interinter_ странно - в некоторых случаях указатели на функции членов класса могут в конечном итоге быть 2x размером нормального указателя функции, поэтому даже не задумываюсь о том, чтобы заставить литье :) – bdonlan

10

Вы должны определить свою функцию обратного вызова как функцию static, если она является функцией-членом!


Лучшая конструкция: определить класс многоразового использования!

Из моего previous answer: (с небольшими изменениями)

Еще лучше было бы определить многоразовый класса с чистой виртуальной функции run() быть реализованы с помощью производных резьбы классов. Вот как это должно быть разработано:

//runnable is reusable class. All thread classes must derive from it! 
class runnable 
{ 
public: 
    virtual ~runnable() {} 
    static DWORD WINAPI run_thread(LPVOID args) 
    { 
     runnable *prunnable = static_cast<runnable*>(args); 
     return prunnable->run(); 
    } 
protected: 
    virtual DWORD run() = 0; //derived class must implement this! 
}; 

class Thread : public runnable //derived from runnable! 
{ 
public: 
    void newthread() 
    { 
     CreateThread(NULL, 0, &runnable::run_thread, this, 0, NULL); 
    } 
protected: 
    DWORD run() //implementing the virtual function! 
    { 
     /*.....your thread execution code.....*/ 
    } 
} 
+0

Я бы использовал шаблон, а не временное наследование. Но общая идея верна. – Puppy

+0

@DeadMG: вы имеете в виду CRTP? – Nawaz

+0

+1, но я сделаю метод 'run' защищенным. –

11

Серьезно, использование станд :: нити (или увеличить :: нить, если ваш компилятор не поддерживает его еще нет):

class CLASS 
{ 
public: 
    void A(); 
private: 
    void B(your args go here); 
}; 

void CLASS::A() 
{ 
    boost::thread(&CLASS::B, this, your args go here); 
} 
+2

+1. Да, обязательно перейдите в std ::/boost :: thread. Более того, вам даже не нужна привязка: 'boost :: thread t (& CLASS :: B, это, ваши аргументы, если они идут);'. Так просто. – usta

+0

@usta: спасибо! исправлено. – ybungalobill