2017-02-23 29 views
1

Мне удалось выполнить обратный вызов без шаблонов классов. Но мое требование - реализовать обратные вызовы с передающими объектами класса, которые находятся в форме шаблона. Я написал свое намерение в main(), но каким-то образом я не могу заставить его работать.Использовать шаблон шаблона в качестве обратного вызова в C++

Я не могу использовать boost и C++ 11 для моей текущей проблемы. Любая помощь будет принята с благодарностью.

// TestProj.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include "glb.h" 
#include "Test.h" 
#include <iostream> 
using namespace std; 

class MyCallBack 
{ 
private: 
    class Callback 
    { 
    public: 
     virtual ~Callback() { } 
     virtual void call() = 0; 
    }; 

    template <typename T> 
    class ClassCallback : public Callback 
    { 
    private: 
     T*  object; 
     void (T::*callback)(); 

    public: 
     ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {} 
     virtual void call() { (object->*callback)(); } 
    }; 

private: 
    Callback*  callback; 

public: 
    MyCallBack() : callback(NULL) { } 
    ~MyCallBack() { delete callback; } 

    template <typename T> 
    MyCallBack(T* obj, void (T::*clbk)()) 
    { 
     callback = new ClassCallback<T>(obj,clbk); 
    } 

    void operator()() 
    { 
     callback->call(); 
    } 
}; 

typedef enum { 
    EVENT1 = 1, 
    EVENT2 = 2, 
    EVENT3 = 4, 
    EVENT4 = 8 
} MyEvent_t; 

template <class EventT> 
class EventHandler 
{ 
public: 
    virtual void on_event(EventT _event) = 0; 
}; 

class MyHandler:public EventHandler<MyEvent_t>{ 

    virtual void on_event(MyEvent_t _event){ 

     switch(_event){ 

      case EVENT1: 
       break; 

      case EVENT2: 
       break; 

     } 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    EventHandler<MyEvent_t> *my_handler = new MyHandler(); 
    MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event); 

    // to check the callback 
    rcb(); 

    return 0; 
} 

Спасибо большое!

+0

Я уверен, что мы можем помочь вам, если вы можете быть более конкретным, как к этому вопросу, и/или уменьшить код. – Potatoswatter

+0

Для начала 'on_event' ожидает' EventT'. Ваш 'void (T :: * callback)();' не учитывает это. –

+0

HI Barrett, да, я знаю, что аргумент отсутствует. Мой вопрос заключается в том, как добавить его. Я новичок в C++ и шаблонах. Также строка MyCallBack rcb (my_handler, & MyHandler :: on_event); имеет тип, обозначенный RS. Должен быть обработчик событий вместо Myhandler. – Jain

ответ

0

Линия

MyCallBack rcb(my_handler,&MyHandler<MyEvent_t>::on_event); 

является проблемой, так как on_event принимает аргумент. Указатель функции-члена, ожидаемый в конструкторе MyCallBack(), не принимает никаких аргументов.

Следующие работы для меня с точки зрения компиляции/сборки. Вам нужно будет выяснить, как заставить его работать в семантической точке зрения.

#include <iostream> 
using namespace std; 

class MyCallBack 
{ 
    private: 
     class Callback 
     { 
     public: 
      virtual ~Callback() { } 
      virtual void call() = 0; 
     }; 

     template <typename T> 
     class ClassCallback : public Callback 
     { 
     private: 
      T*  object; 
      void (T::*callback)(); 

     public: 
      ClassCallback(T* obj, void (T::*clbk)()) : object(obj), callback(clbk) {} 
      virtual void call() { (object->*callback)(); } 
     }; 

    private: 
     Callback*  callback; 

    public: 
     MyCallBack() : callback(NULL) { } 
     ~MyCallBack() { delete callback; } 

     template <typename T> 
     MyCallBack(T* obj, void (T::*clbk)()) 
     { 
      callback = new ClassCallback<T>(obj,clbk); 
     } 

     void operator()() 
     { 
     callback->call(); 
     } 
}; 

typedef enum { 
    EVENT1 = 1, 
    EVENT2 = 2, 
    EVENT3 = 4, 
    EVENT4 = 8 
} MyEvent_t; 

template <class EventT> 
class EventHandler 
{ 
    public: 
     void event() { on_event(EventT()); } 
     virtual void on_event(EventT _event) = 0; 
}; 

class MyHandler:public EventHandler<MyEvent_t>{ 

    virtual void on_event(MyEvent_t _event){ 

     switch(_event){ 

     case EVENT1: 
      break; 

     case EVENT2: 
      break; 

     default: 
      break; 
     } 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    EventHandler<MyEvent_t> *my_handler = new MyHandler(); 
    MyCallBack rcb(my_handler,&EventHandler<MyEvent_t>::event); 

    // to check the callback 
    rcb(); 

    return 0; 
} 
0

Я думаю, что вы пытаетесь достичь - это шаблон действия. Посмотрите здесь: https://en.wikipedia.org/wiki/Command_pattern

А теперь к реализации:

#include <iostream> 
#include <memory> 

struct Action { 
    virtual void execute() = 0; 
}; 

struct SomeAction : public Action { 
    void execute() { 
     std::cout << "SomeAction" << std::endl; 
    } 
}; 

struct SomeOtherAction : public Action { 
    void execute() { 
     std::cout << "SomeOtherAction" << std::endl; 
    } 
}; 

class EventHandler { 

    std::unique_ptr<Action> action; // The unique ptr will delete action if the event handler is destroyed 

public: 
    EventHandler() : 
     action(new SomeAction()) 
    { 

    } 
    void setAction(Action* newAction) { 
     action = std::unique_ptr<Action>(newAction); 
    } 
    void eventCalled() { 
     // This function is invoked from the outside if the event happens 
     action->execute(); 
    } 
}; 

int main() { 
    EventHandler eventHandler; 

    //Some event is called 
    eventHandler.eventCalled(); // Output "SomeAction" 


    // We change the action later in time 
    eventHandler.setAction(new SomeOtherAction()); 
    // Another Event gets called 
    eventHandler.eventCalled(); // Output "SomeOtherAction" 
    return 0; 
} 
+0

Если вам непонятно, как отобразить событие с событием (или несколькими действиями), не стесняйтесь оставлять комментарий. – OutOfBound

Смежные вопросы