Ilya Гость
|
Добавлено: Ср Мар 05 2003 22:51 Заголовок сообщения: Функция потока - член класса, чего сдлеать, чтобы исправить указатель на неё? |
|
|
Мне нужно, чтобы конструктор объекта создавал новый поток. При этом, функция потока также должна быть методом этого объекта. Казалось бы - нормальные требования. Но у меня возникает проблема, которую я не знаю как решить. Проблема заключается в следующем: третий аргумент функции __beginthreadex имеет тип void(__stdcall*) (void*), но если функция потока определена как метод класса, то указатель на неё будет иметь вид void(__stdcall Bug:: *) (void *). Расскажите пожалуйста как проблему решить (красиво)??? Я пытался сделать функцию потока friend'ом, чтобы "вытащить" её в глобальную область видимости, но она, естественно использует переменные и другие методы класса, при попытке вызвать функцию-метод с помощью Bug::Chase() (например) происходит следующая ругань: 'Bug::Chase' : illegal call of non-static member function. See declaration of 'Chase'
Дело в том, что я совсем новичок и разобраться самому очень тяжело. Поможите, чем можите! Буду благодарен. |
|
chaka Гость
|
Добавлено: Пт Мар 07 2003 14:30 Заголовок сообщения: Re: Функция потока - член класса, чего сдлеать, чтобы исправить указатель на неё? |
|
|
Дело в том, что при вызове функции-члена в стек первым параметром неявно помещается указатель на экземпляр класса (this). Так что использование функции члена и обычной глобальной функции хоть и семантически идентичны, но все же различаются. Система при создании потока требует именно адрес глобальной точки входа, она ничего не знает о this и т.д., по этому возникают некоторые неудобства при использовании объектно-ориентированных способов программирования в "несовсем" объектно-ориентированной системе. Как правило решение выглядит следующим образом. 1. Создается интерфейсный класс, который определяет точку входа, которыю будет использовать система при создании нити и декларируется рабочаяя функция, которая будет выполнять необходимые действия, но уже в контексте заданного класса. 2. Нужный нам класс наследует от этого абстрактного интерфейсного класса. 3. Создается поток и в качестве указателя на точку входа передается метод интерфейсного класса.
Итак 1: //entry.hpp #include // EXIT_SUCCESS, EXIT_FAILURE #include class IEntry{ public: virtual unsigned int work_func() = 0; //перегружаем в производном классе для выполнения полезной работы static unsigned int __stdcall entry(void* pv){ //static - чтобы убрать this IEntry* p = reinterpret_cast(pv); unsigned int dwRes = 0; try{ dwRes = p->work_func(); } catch(...){ assert(0); dwRes = EXIT_FAILURE; } return dwRes; } }; 2: //worker.hpp #include "entry.hpp" class CWorker : public IEntry{ public: virtual unsigned int work_func(); //рабочая функция }; //worker.cpp #include "worker.hpp" #include // cout #include // endl using namespace std; unsigned int CWorker::work_func(){ cout #include void f(){ CWorker w; unsigned int dwThreadId; HANDLE h = (HANDLE)_beginthreadex(0, 0, IEntry::entry, static_cast(&w), 0, &dwThreadId); Sleep(10000); //чтобы успела отбаротать вновь созданная нить } int main(int /*argc*/, char** /*argv*/){ f(); return EXIT_SUCCESS; } P.S. Вот, как бы, и все, единственно - форма для ввода ответов не очень располагает для написания исходных кодов, так что если все, что я здесь написал будет одним сплошным куском текста, а не отформатированным листингом, то заранее извиняюсь. Ну, а если где есть описки, так это с кем не бывает |
|