Callback in C++ Different Implementation between Old Style and Modern C++

古早 C++ 的 Callback 實作一般是這樣的。

class Callback
{
  virtual void handler( int event );
};

class SourceClass
{
  void func()
  {
     if (cb_ != NULL)
      cb_->handler( 123 );
  }
  void set_callback( Callback* callback )
  {
    cb_ = callback;
  }
    
  Callback* cb_;
};

class ListenerClass
{
  class MyCallback : public Callback()
  {
    void handler( int event ) override
    {
        // handle the event (123) from SourceClass
    }
  };
    
  ListenerClass()
  {
    src_object_.set_callback( new MyCallback() );
  }
    
  SourceClass src_object_;
};

也就是把 Callback 做成一個 Class (i.e. Class Callback),然後再做一個繼承該 Callback 的物件 (i.e. Class ListenerClass::MyCallback) 裡面自己實作要如何處理 Callback 回傳的訊息,最後用個 Pointer 傳到底層 (i.e. Class SourceClass) 去讓底層使用。

這做法沒甚麼問題,Java 也是這樣做的,但是就是寫 code 很麻煩,為了一個 Callback 還要建立另外二個 Class。

後來 C++11 加了新的做法,對我來說就是把 C 的 function pointer 拿來改進,讓 Class Member 也能當作 function pointer 使用。

class SourceClass
{
  void func()
  {
     if (cb_ != nullptr)
      cb_( 123 );
  }
  void set_callback(std::function<void(int)> callback)
  {
    cb_ = callback;
  }
  
  std::function<void(int)> cb_;
};

class ListenerClass
{
  ListenerClass()
  {
    auto cb_func = std::bind(
      &ListenerClass::handler,
      this,
      std::placeholders::_1);
    src_object_.set_callback( cb_func );
  }
    
  void handler( int event )
  {
    // handle event 123 here
  }
    
  SourceClass src_object_;
}

C++11 的做法在架構上精簡了很多,少了二個中間的 Class 宣告看起來清楚多了。