2017-02-23 1 views
1

Ich konnte den Rückruf ohne Klassenvorlagen arbeiten. Aber meine Anforderung besteht darin, Callbacks mit übergebenen Klassenobjekten in Vorlagenform zu implementieren. Ich habe meine Absicht hauptsächlich geschrieben(), aber irgendwie kann ich es nicht funktionieren lassen.Verwenden Sie Klassenvorlage als Rückruf in C++

Ich kann Boost und C++ 11 nicht für mein aktuelles Problem verwenden. Jede Hilfe würde sehr geschätzt werden.

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

Vielen Dank für alle Leads !!!

+0

Ich bin sicher, dass wir Ihnen helfen können, wenn Sie spezifischere wie für die Ausgabe sein können, und/oder den Code zu reduzieren. – Potatoswatter

+0

Zunächst erwartet 'on_event'' EventT'. Ihr 'void (T :: * callback)();' berücksichtigt dies nicht. –

+0

HI Barrett, ja ich bin mir bewusst, dass Argument fehlt. Meine Frage ist, wie man es hinzufügt. Ich bin neu in C++ und Templates. Auch die Zeile MyCallBack rcb (my_handler, & MyHandler :: on_event); hat einen Typ wie RS darauf hingewiesen. Sollte Event Handler anstelle von Myhandler sein. – Jain

Antwort

0

Die Linie

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

ist ein Problem, da on_event ein Argument nimmt. Der Memberfunktionszeiger, der im Konstruktor MyCallBack() erwartet wird, nimmt keine Argumente an.

Das folgende funktioniert für mich aus einer Compile/Build-Sicht. Sie müssen herausfinden, wie Sie es für einen semantischen Standpunkt arbeiten lassen.

#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

Ich denke, was Sie versuchen zu erreichen, ist das Aktionsmuster. Werfen Sie einen Blick hier: https://en.wikipedia.org/wiki/Command_pattern

Und nun zur Umsetzung:

#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

Wenn Ihnen unklar ist, wie Sie vom Ereignis zur Aktion (oder zu möglichen Mehrfachaktionen) mappen, können Sie einen Kommentar hinterlassen. – OutOfBound

Verwandte Themen