2013-12-16 45 views
0

我想模擬Windows中的C#事件驅動編程使用C++進行編程。當調用list.clear()時出現運行時錯誤

我要完成的,以這種方式:

  1. 使用列表容器來保存函數指針
  2. 覆蓋+ =運算符,讓類事件可以 這種方式添加功能事件+ = handlerFuncName
  3. 覆蓋的()操作,所以我們可以調用函數列表

事件CLAS S:

template<class Sender_Type, class Args_Type> 
class Event{ 
private: 
    typedef void(*HFUN)(Sender_Type *, Args_Type); 
    list<HFUN> handlers; 
public: 
    void operator +=(HFUN handler){ 
     handlers.push_back(handler); 
    } 

    void operator()(Sender_Type *sender, Args_Type e){  
     for (list<HFUN>::iterator it = handlers.begin(); it != handlers.end(); it++) 
      (*it)(sender, e); 
    } 

    ~Event(){ printf("Release..\n"); } 
}; 

,這裏是一個實例:

EventArgs類的定義和窗口類:

class EventArgs{ }; 

class Win32Window 
{ 
public: 
    // event definition 
    Event<Win32Window, EventArgs> Loaded; 

    // ctor 
    Win32Window(){ 
     // ... 
     // trigger the Loaded event 
     Loaded(this, EventArgs()); 
    } 
    // ... 
}; 

事件處理函數的定義:

void Window_Loaded(Win32Window *sender, EventArgs e){ 
    MessageBox(NULL, "Window_Loaded", "xx", 0); 
} 

主要功能:

Win32Window wnd; 
//add the event handler function 
wnd.Loaded += Window_Loaded; 

它可以工作,但是當窗口關閉時,list.clear()中出現運行時錯誤! 這是一個例外的snapshot

+0

甚至不能看到你的圖像... –

+0

什麼是HFUN?你能否顯示初始化和清除這個列表的代碼,事件處理程序代碼的問題是不必要的。請嘗試並減少到[SSCCE](http://sscce.org/)。 –

+0

成員函數指針顯然不是答案。嘗試閱讀Functors。 – pmr

回答

1

這是,我認爲,正是std::function打算幫助的那種問題。嘗試這樣對於初學者:

#include <functional> 
#include <iostream> 
#include <vector> 

template <typename Sender, typename... Args> 
class Event 
{ 
    using FuncType = std::function<void(Sender&, Args...)>; 
    std::vector<FuncType> vec; 

public: 
    Event& operator+=(FuncType f) { 
     vec.push_back(f); 
     return *this; 
    } 

    void operator()(Sender& s, Args... a) { 
     for (auto& f : vec) { 
      f(s, a...); 
     } 
    } 
}; 


struct Window 
{ 
    Event<Window, int, int> resized; 

    void resize(int width, int height) { 
     // blah blah 
     resized(*this, width, height); 
    } 

}; 

int main() 
{ 
    Window w; 

    w.resized += [](Window&, int w, int h) { 
     std::cout << "Window resized to " << w << " by " << h << std::endl; 
    }; 

    w.resize(800, 600); 
} 

注意,此方法可以讓你不僅可以使用常規的功能作爲事件左撇子,而且Lambda表達式(如所示),並且也起到對象。

+0

非常感謝。這對我很有幫助。 – Sleen