Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Классы: как "организовать" такой код?


Автор: Alca 12.12.2009, 20:38
Код

void vOnExitHandle() {
    //...
}
//...
CWorkThread *pthThread = new CWorkThread();
pthThread->m_uiIndex = i;
pthThread->vOnExit   = vOnExitHandle;    //как "организовать" такой код ???

pthThread->bCreate();
pthThread->bResume();

Автор: Alexeis 12.12.2009, 20:44
Alca, вопрос в чем? Как создавать обработчики или как выполнить финальный обработчик контексте основного потока?

Автор: Alca 12.12.2009, 20:49
Как создавать обработчики

Добавлено через 1 минуту и 47 секунд
Код

pthThread->vOnExit = ...

Автор: Alexeis 12.12.2009, 21:08
объявить в классе переменную указатель на функцию. Примерно так.
Код

...
void (*vOnExit) (void);
...


Добавлено через 1 минуту и 50 секунд
  Эта тема хорошо раскрыта тут http://alenacpp.blogspot.com/2007/04/blog-post.html

Автор: Alca 12.12.2009, 21:15
Ок. А как внутри класса CWorkThread "прикрутить" этот указатель?

Автор: Alexeis 12.12.2009, 21:18
Цитата(Alca @  12.12.2009,  20:15 Найти цитируемый пост)
Ок. А как внутри класса CWorkThread "прикрутить" этот указатель?

  Собственно я это и написал. 
Код

class CWorkThread
{
...
public:
  void (*vOnExit) (void);
...
};
 

А присвоение обработчика уже показано тут 

Цитата(Alca @  12.12.2009,  19:38 Найти цитируемый пост)
pthThread->vOnExit   = vOnExitHandle;    //как "организовать" такой код ???


Именно так и нужно.

Автор: Alca 12.12.2009, 21:19
Сейчас гляну. Спасибо.

Добавлено @ 21:21
Код

class CWorkThread
{
...
public:
  void (*vOnExit) (void);
  void vMethodA() {
      vOnExit();  //надо вызвать метод внутри класса
  }
...
};


Автор: Alexeis 12.12.2009, 21:34
вызывается по другому
Код

(*vOnExit)();

Автор: Abyx 12.12.2009, 21:35
если CWorkThread - часть библиотеки, а обработчик предоставляет пользователь, лучше использовать шаблоны или boost::function<>

Автор: Alca 12.12.2009, 21:38
Цитата

если CWorkThread - часть библиотеки, а обработчик предоставляет пользователь, 

 smile 
Цитата

лучше использовать шаблоны или boost::function<>

не хочеться буст прикручивать 

Автор: Alca 12.12.2009, 22:33
а как вызвать vOnExit из статического метода класса?

Добавлено через 12 минут и 1 секунду
вроде так:
Код

...
pthThis->vOnExit(); 
...

Автор: Alexeis 12.12.2009, 22:46
Цитата(Alca @  12.12.2009,  21:33 Найти цитируемый пост)
а как вызвать vOnExit из статического метода класса? 

  Можно, если статический метод получает как параметр указатель на экземпляр объекта.

Автор: Alca 12.12.2009, 22:50
Со статическим методом вроде разобрался.

пытаюсь присвоить обработчик:
Код

UINT CXThreadPool::uiOnRun(VOID *pData) { 
    ....
    pthThread->vOnExit   = _vOnTest; 
    ...
}
   
Код

Error    1    error C3867: 'CXThreadPool::_vOnTest': function call missing argument list; use '&CXThreadPool::_vOnTest' to create a pointer to member    d:\xlib\source\sync\cxthreadpool.cpp    205
Error    2    error C2440: '=' : cannot convert from 'void (__thiscall CXThreadPool::* )(void)' to 'void (__cdecl *)(void)'    d:\xlib\source\sync\cxthreadpool.cpp    205

 smile

Добавлено @ 22:52
1-ю ошибку исправил
Код

pthThread->vOnExit   = &CXThreadPool::_vOnTest; 

Как вторую решить?
Код

Error    1    error C2440: '=' : cannot convert from 'void (__thiscall CXThreadPool::* )(void)' to 'void (__cdecl *)(void)'    d:\xlib\source\sync\cxthreadpool.cpp    205



Автор: Alexeis 12.12.2009, 23:14
  Компилятор прав функция класса и функция это разные вещи. функция класса + указатель на объект нам дают уже замыкание. Это совсем другая конструкция. На билдере это делается через расширение языка __closure . В студии тоже что-то такое есть, но я уже не помню 

Автор: Леопольд 13.12.2009, 21:48
Цитата(Alca @  12.12.2009,  21:38 Найти цитируемый пост)
не хочеться буст прикручивать  

Ну, ежели нужен велосипед, то мог бы сойти такой:
Код

#include <iostream>
#include <memory>

class Functor{
public:
    virtual void operator()() const = 0;
    virtual ~Functor(){}
};

class Object{
public:
    void toCall(){
        std::cout<<"Object::toCall is invoked"<<std::endl;
    };

    void toCall() const{
        std::cout<<"const Object::toCall is invoked"<<std::endl;
    };

    Functor* createFunctor(){
        class OFunctor: public Functor{
            Object& _ref;
        public:
            OFunctor(Object& ref): _ref(ref){}
            virtual void operator()() const{
                _ref.toCall();
            }
        };

        return new OFunctor(*this);
    }

    Functor* createFunctor() const{
        class OFunctor: public Functor{
            const Object& _ref;
        public:
            OFunctor(const Object& ref): _ref(ref){}
            virtual void operator()() const{
                _ref.toCall();
            }
        };

        return new OFunctor(*this);
    }
};

int main () {

    Object obj;
    std::auto_ptr<Functor> ptr(obj.createFunctor());
    (*ptr)();

    const Object cobj;
    std::auto_ptr<Functor> cptr(cobj.createFunctor());
    (*cptr)();

    return 0;
}

Автор: Alca 14.12.2009, 10:55
Цитата

Ну, ежели нужен велосипед

Можно попробывать 

Вот мои классы, как этот велик приспособить? 
Код

/****************************************************************************
*    класс CXThread
*
*****************************************************************************/

//---------------------------------------------------------------------------
//CXThread.h
class CXThread {
    //...
    
    public:
        VOID   (*vOnExit)();
    
    protected:
        virtual UINT uiOnRun(VOID *pvParam) = 0;
                
    private:
        static UINT WINAPI _s_uiStartFunc(VOID *pvParam);
    
    //...
};
//---------------------------------------------------------------------------
//CXThread.cpp
/*static*/ UINT WINAPI CXThread::_s_uiStartFunc(VOID *pvParam) {
    CXThread *pthThis = static_cast<CXThread *>(pvParam); 
    pthThis->vOnExit(); 
    
    //...
    
    return uiRes;
}
//---------------------------------------------------------------------------


Код

/****************************************************************************
*    класс CXThreadPool
*
*****************************************************************************/

//---------------------------------------------------------------------------
//CXThreadPool.h
#include <XLib/Sync/CXThread.h>
//---------------------------------------------------------------------------
class CXThreadPool : public CXThread {
    //...
    protected:
        virtual UINT uiOnRun    (VOID *pData);    /*overload from CXThread*/
        
    private:
        std::vector<CWorkThread *> _m_vecpthWorkThreads;
        
        VOID _vOnTest(VOID) {
            ::MessageBox(0, _T("Test"), _T(""), MB_OK);
        }        
    //...        
};
//---------------------------------------------------------------------------
//CXThreadPool.cpp
UINT CXThreadPool::uiOnRun(VOID *pData) { 
    //...
    
    CXThreadPool *pthTemp = new CXThreadPool();
    
    _m_vecpthWorkThreads.at(_m_uiCurrTask) = pthTemp;
    _m_vecpthWorkThreads.at(_m_uiCurrTask)->vOnExit  = &CXThreadPool::_vOnTest; /*<<< здесь ругается:
    Error    1    error C2440: '=' : cannot convert from 'void (__thiscall CXThreadPool::* )(void)' to 'void (__cdecl *)(void)'
    */
    _m_vecpthWorkThreads.at(_m_uiCurrTask)->bCreate();
    _m_vecpthWorkThreads.at(_m_uiCurrTask)->bResume();

    _m_uiCurrTask ++;

    //...

    return uiRes;
}
//---------------------------------------------------------------------------

Автор: Alca 14.12.2009, 11:55
Ну или как с бустом будет?

Автор: Леопольд 14.12.2009, 14:18
Цитата(Alca @  14.12.2009,  11:55 Найти цитируемый пост)
Ну или как с бустом будет? 


Код

#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>

class Invoker{
    typedef boost::function<void ()> Functor;
    Functor _functor;

public:
    template<typename F>
    void setFunctor(F functor){ // Attention! Transmission by value, and not by reference.
        _functor = functor;
    }
    void invoke(){
        _functor();
    }
};

void plainFunction(){
    std::cout<<"function"<<std::endl;
}


struct Object{
    void foo(){
        std::cout<<"Object::foo"<<std::endl;
    }
};

struct FunctObj{
    void operator()(){
        std::cout<<"FunctObj::operator()"<<std::endl;
    }
};

int main(){
    
    Invoker invoker;

    Object obj;
    invoker.setFunctor( boost::bind(&Object::foo, obj) );
    invoker.invoke();
    
    FunctObj fo;
    invoker.setFunctor(fo);
    invoker.invoke();

    invoker.setFunctor(plainFunction);
    invoker.invoke();

    return 0;
}


Должен предупредить что я не использую boost активно. Функторы вообще первый раз в этом примере. Руководствовался http://sources.ru/wiki/doku.php?id=doc:cpp:boost:function и немного почитал boost.org

Автор: Alca 14.12.2009, 15:13
Леопольд, спасибо. Буду разбираться.

Автор: Alca 14.12.2009, 15:44
Код

boost::function<void (CXThreadPool*)> f;
f = &CXThreadPool::_vOnTest;
///f(this);
_m_vecpthWorkThreads.at(_m_uiCurrTask)->_vOnExit  =  f ;   

Код

Error    1    error C2440: '=' : cannot convert from 'boost::function<Signature>' to 'void (__cdecl *)(void)'

 smile

Добавлено через 2 минуты и 9 секунд
Темный лес  smile 

Автор: Alca 14.12.2009, 17:24
Решил проблему с помощью http://dobrokot.nm.ru/cpp/CppMethodsCallback.html.


FAQ:
Цитата

- Winnie.Closure
  http://dobrokot.nm.ru/cpp/CppMethodsCallback.html

- Указатели на функции-члены и реализация самых быстрых делегатов на С++.
  http://www.rsdn.ru/article/cpp/fastdelegate.xml
  http://www.codeproject.com/cpp/FastDelegate.asp

- Как сделать callback метод? Почему я не могу присвоить метод указателю на функцию?
  http://www.gamedev.ru/faq/?id=34

- boost::bind
  http://www.boost.org/doc/libs/1_41_0/libs/bind/bind.html  

- boost::function
  http://www.boost.org/doc/libs/1_41_0/doc/html/function.html
  http://sources.ru/wiki/doku.php?id=doc:cpp:boost:function
  http://forum.sources.ru/index.php?showtopic=215446

- Better way to call member function using function pointer?
  http://visualcpp.lite-programa.ru/?news=3901

- The Function Pointer Tutorials
  http://www.newty.de/fpt/callback.html  

- Указатели на функцию, коллбэки и функторы
  http://alenacpp.blogspot.com/2007/04/blog-post.html

- Использование функции-члена в качестве аргумента
  http://forums.realcoding.net/index.php?showtopic=5936&st=0&p=35304&#entry35304

- Передача указателя на функцию-член одного класса в функцию другого класса, ...
  http://forum.sources.ru/index.php?showtopic=263592&view=showall

- Указатели на компоненты класса. Доступ по указателю
  http://www.citforum.ru/programming/cpp_march/cpp_082.shtml

- Указатель на функцию класса 
  http://www.sql.ru/Forum/actualthread.aspx?tid=713636
  http://forum.shelek.ru/index.php/topic,5088.0.html
  http://www.parashift.com/c++-faq-lite/pointers-to-members.html
  http://www.rsdn.ru/forum/cpp/1656623.flat.aspx#1656623
  http://forum.sources.ru/index.php?showtopic=282609&view=showall
  http://forum.vingrad.ru/forum/topic-159810.html
  http://www.intuit.ru/department/pl/plintro/11/2.html
  http://forum.codenet.ru/showthread.php?t=40087
  http://www.interface.ru/home.asp?artId=8221
  http://netcode.ru/cpp/?lang=&katID=6&skatID=44&artID=571
  http://forum.sources.ru/index.php?showtopic=60397
  http://forum.sources.ru/index.php?showtopic=70190
  http://forum.sources.ru/index.php?showtopic=38247
  http://forum.sources.ru/index.php?showtopic=51174
  http://forum.sources.ru/index.php?showtopic=45336
  http://www.sources.ru/cpp/faqs/90.htm
  http://www.gamedev.ru/tip/?id=62
  http://leprecon.pisem.net/faq_213.htm
  http://forum.shelek.ru/index.php/topic,3979.0.html
 http://www.partow.net/programming/templatecallback/index.html

Автор: xvr 15.12.2009, 12:12
Цитата(Alca @ 14.12.2009,  15:44)
Код

boost::function<void (CXThreadPool*)> f;
f = &CXThreadPool::_vOnTest;
///f(this);
_m_vecpthWorkThreads.at(_m_uiCurrTask)->_vOnExit  =  f ;   

Код

Error    1    error C2440: '=' : cannot convert from 'boost::function<Signature>' to 'void (__cdecl *)(void)'

 smile

_vOnExit тоже должен быть типа boost::function<void (CXThreadPool*)>, разве не очевидно?  smile 

Автор: Alca 15.12.2009, 12:16
Цитата

разве не очевидно

xvr, спасибо. C бустом в лоб не сталкивался, поэтому знаниния в этой области поверхностные.
Теперь буду знать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)