簡體   English   中英

C ++回調—如何解耦回調類型

[英]C++ Callback — How to decouple the call back type

例如,在下面的偽代碼中,類B需要通過B :: m_cb成員調用A :: Action()。

目的是如何創建一個通用的非模板Callback類,因此“ B”不必是模板,並且“ CallBack”可以保存任何類型的函數簽名。

我曾經使用過這樣的代碼,但現在找不到該實現。 我只記得:
-“ CallBack”本身不是模板,但包含成員模板
-輔助函數模板make_callback將實例化CallBack對象

誰能給一個poiinter?

Class A
{
public:
   void Action(){//...};
};

class CallBack
{
   //...
   // CallBack it self it is a NOT a template
   // It can wrap member template though
};

class B
{
public:
   void SetCallback(CallBack to){
      m_cb = to;
   }
   void do_something()
   {
      //...
      m_cb.Execute();
      //...
   }

private:
   CallBack m_cb;

};

int main()
{
   A obj1;
   CallBack cb = make_callback(&obj1, &A::Action);
   B obj2;
   obj2.SetCallback(cb);
   //....
   obj2.do_something();
}

這是我從同一網站獲得的示例代碼。 我試圖對其進行一些改進,以便它可以容忍任意回調函數的返回類型。 但是它仍然不能像第18行那樣處理任意數量的參數。此外,T是指向成員函數的指針,該成員函數應取決於C。我不知道如何執行此操作。

#include <iostream>
#include <memory>

// INTERNAL CLASSES

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

template<class C, class T>
class CallbackSpec : public CallbackSpecBase
{
  public:
    CallbackSpec(C& o, T m) : obj(o), method(m) {}
/*line 18*/    void operator()(...) const { (&obj->*method)(); } // how to pass "..." into method(...)

  private:
    C& obj;
    T method;
};

// PUBLIC API

class Callback
{
  public:
    Callback() {}

    void operator()() { (*spec)(); }

    template<class C, class T>
      void set(C& o, T m) { spec.reset(new CallbackSpec<C, T>(o, m)); }

  private:
    std::auto_ptr<CallbackSpecBase> spec;
};

// TEST CODE

class Test
{
  public:
    void foo() { std::cout << "Working" << std::endl; }
    void bar() { std::cout << "Like a charm" << std::endl; }
};

int main()
{
  Test t;
  Callback c;
  c.set(t, &Test::foo);
  c();
  c.set(t, &Test::bar);
  c();
}

您正在尋找的是std::function (C ++ 0x)/ boost::function 它們使用類型擦除來使函數像一流的對象一樣工作。 您可以執行以下操作:

class A
{
public:
    void Action() {//...};
};

class B
{
public:
    template <typename Func>
    void SetCallback(Func func) {
        m_cb = func;
    }

    void do_something() {
        m_cb(); // whatever function
    }

private:
    std::function<void()> m_cb; // anything callable with no arguments
};

int main()
{
    A obj1;
    B obj2;

    obj2.SetCallback(make_callback(&obj1, &A::Action));
    // or:
    obj2.SetCallback(std::bind(&obj1, &A::Action)); // or boost::bind

    obj2.do_something();
}

我已經根據本文實現了一種回調機制:

http://www.codeproject.com/KB/cpp/CPPCallback.aspx

通過該實現,您可以將全局函數靜態成員函數 或非靜態成員函數用作回調。

本文介紹了如何將委托對象創建為所有這些類型的仿函數。 您的class B可以具有一個委托對象作為成員,以及一個用於注冊回調函數的方法和用於對其進行調用的方法。 class B和您的回調函數都不必模板化! 如果將非靜態成員函數用作回調,則委托對象包含一個對象指針,以及指向模板化靜態包裝器函數的指針。 在該包裝函數中,存儲了指向回調函數的函數指針。 它可以直接調用,也可以在綁定到傳遞的對象指針之前調用。

class B
{
  public:
    void SetCallback(CDelegate f_Delegate)
    {
      m_Delegate = f_Delegate;
    }
    static void do_something()
    {
      //...
      m_Delegate();
      //...
    }

  private:
    static CDelegate m_Delegate;
};

更新:

該機制的描述如下: 5年后,還有什么比“最快的C ++委托”更好的了嗎?

這實際上並不能回答您的問題,因為回調必須是模板,除非您想通過void*傳遞參數(在我看來,這完全是瘋狂的主意)。

我問了一個類似的問題: 這個可變參數模板示例有什么問題?

答案之一給出了一個完整的解決方案:

#include <memory>

template< typename R, typename ... Args >
class CallbackBase
{
public:
    typedef std::shared_ptr< CallbackBase< R, Args... > >
            CallbackPtr;

    virtual ~CallbackBase()
    {
    }
    virtual R Call(  Args ... args) = 0;
};

template< typename R, typename ... Args >
class FunctionCallback : public CallbackBase< R, Args... >
{
public:
    typedef R (*funccb)(Args...);

    FunctionCallback( funccb  cb_ ) : 
        CallbackBase< R, Args... >(),
        cb( cb_ )
    {
    }
    virtual ~FunctionCallback()
    {
    }
    virtual R Call(Args... args)
    {
      return cb( args... );
    }
private:
  funccb cb;
};

template < typename R, typename ...Args >
typename CallbackBase< R, Args... >::CallbackPtr
    MakeCallback( R (*cb)(Args...)  )
{
    typename CallbackBase< R, Args... >::CallbackPtr
        p( new FunctionCallback< R, Args... >( cb )
);
    return p;
}

bool Foo_1args( const int & t)
{
    return true;
}
int main()
{
    auto cbObj = MakeCallback( & Foo_1args );
}

希望能幫助到你。 如果您討厭模板,則始終可以使用typedef。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM