【问题标题】:Use class template as callback in C++在 C++ 中使用类模板作为回调
【发布时间】:2017-02-23 06:12:57
【问题描述】:

我能够在没有类模板的情况下使回调工作。但我的要求是通过传递模板形式的类对象来实现回调。我已经在 main() 中写了我的意图,但不知何故我无法让它工作。

对于当前的问题,我无法使用 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;
}

非常感谢任何线索!!!

【问题讨论】:

  • 我相信我们可以帮助您,如果您可以更具体地了解问题和/或减少代码。
  • 对于初学者来说,on_event 需要 EventT。你的void (T::*callback)(); 没有考虑到这一点。
  • 嗨,巴雷特,是的,我知道缺少参数。我的问题是如何添加它。我是 C++ 和模板的新手。还有行 MyCallBack rcb(my_handler,&MyHandler::on_event);具有 RS 指出的类型。应该是事件处理程序而不是 Myhandler。

标签: c++ class templates c++03


【解决方案1】:

线

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

【讨论】:

    【解决方案2】:

    我认为您想要实现的是动作模式。 看看这里: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;
    }
    

    【讨论】:

    • 如果您不清楚如何从事件映射到动作(或可能的多个动作),请随时发表评论。
    猜你喜欢
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2018-04-06
    相关资源
    最近更新 更多