2015-04-03 72 views
1

我來自C#並試圖在C++ 11中實現一個簡單的事件/事件處理程序模式,我相信通用名稱是觀察者和信號,我知道有增強庫和其他人,但我不想使用任何外部庫。C++ 11觀察者傳遞參數通知

在網上搜索時,我發現我需要的一個簡單的實現,所以我採取和修改了代碼,它工作正常。

我的問題是,當註冊events/observers時傳遞的參數,而不是當我提高/信號/通知我覺得有點尷尬。

class EventManager 
{ 
private: 

static std::map<EventType, std::vector<std::function<void()>>> _eventHandlers; 

public: 
EventManager() = default; 


template <typename EventHandler> 
static void RegisterEventHandler(EventType&& eventType, EventHandler&& eventHandler) 
{ 
    EventManager::_eventHandlers[std::move(eventType)].push_back(std::forward<EventHandler>(eventHandler)); 
} 

static void Raise(const EventType& event) 
{ 
    for (const auto& eventHandler : EventManager::_eventHandlers.at(event)) 
    { 

     eventHandler(); 
    } 
} 

// disallow copying and assigning 
EventManager(const EventManager&) = delete; 
EventManager& operator=(const EventManager&) = delete; 


}; 

任何人都可以通過在提高事件時添加接受參數的功能來擴展以下代碼嗎?

回答

1

我相信這能解決你的問題:

// g++ -std=c++11 -o /tmp/events /tmp/events.cpp && /tmp/events 
// handler=1 arg=1 
// handler=2 arg=1 
// handler=1 arg=2 
// handler=2 arg=2 

#include <functional> 
#include <map> 
#include <vector> 

template<class EventType, class... HandlerArgs> 
class EventManager 
{ 
public: 
    using EventHandler = std::function< void(HandlerArgs...) >; 

    void register_event(EventType&& event, EventHandler&& handler) 
     { 
      _handlers[std::move(event)].push_back(std::forward<EventHandler>(handler)); 
     } 

    void raise_event(const EventType& event, HandlerArgs&&... args) 
     { 
      for (const auto& handler: EventManager::_handlers.at(event)) { 
       handler(std::forward<HandlerArgs>(args)...); 
      } 
     } 

private: 
    std::map<EventType, std::vector<EventHandler>> _handlers; 

}; 

int main(int argc, char **argv) 
{ 
    EventManager<int, int> m; 
    m.register_event(1, [](int arg) { printf("handler=%d arg=%d\n", 1, arg); }); 
    m.register_event(1, [](int arg) { printf("handler=%d arg=%d\n", 2, arg); }); 
    m.raise_event(1, 1); 
    m.raise_event(1, 2); 
} 

PS:我刪除了所有關於非copiability和這樣的代碼,因爲它是不相關的這個問題。

+0

感謝您的答案,但如果方法是靜態的,因爲您需要初始化EventManager類併爲事件處理程序定義參數/參數模板,所以這不起作用,對吧? – Ronny 2015-04-10 17:31:18

+0

使用靜態方法和靜態'_handlers'成員將工作得很好。 – 2015-04-12 18:54:57

+0

好的,謝謝如果你不介意的話,我會嘗試修改代碼並回復給你,但是,由於你付出了時間和精力來幫助我,謝謝,謝謝。 – Ronny 2015-04-12 21:14:03

0

由於我還沒有得到任何答案,我想通過這樣做的方式,但我不喜歡它,因爲我想要一個更好的方法,但很好地創建一個靜態類,每個事件具有靜態變量,在提高事件之前,調用者將設置這些變量,處理程序將讀取並重置它們。這是危險的方法,特別是對於多線程,因爲一個或多個線程可能會在多線程引發同一事件的同時更改值,所以我必須實施一些鎖定功能以確保線程安全。

是的,我知道它不是最好的方法,但因爲我不是C++的專家,這個問題沒有得到任何意見和答案,所以這是我接下來的方法。