2015-10-21 28 views
1

我想編寫C#的C++事件類是這樣的:C++事件模板類

template< typename ListenerType > 
class Event 
{ 
private: 

    std::vector< ListenerType * > m_aListeners; 

public: 

    void operator += (ListenerType * pListener) 
    { 
     m_aListeners.push_back(pListener); 
    } 

    void operator -= (ListenerType * pListener) 
    { 
     std::vector< ListenerType * >::reverse_iterator revIter = m_aListeners.rbegin(); 
     for(; revIter != m_aListeners.rend(); ++revIter) 
      if(revIter == pListener) 
      { 
       m_aListeners.remove(revIter); 
       break; 
      } 
    } 
}; 

class DataReceivedEvent : public Event<DataReceivedListener> 
{ 
public: 

    void Trigger(const byte_t * pData) 
    { 
     for(size_t nI = 0; nI < m_aListeners.size(); ++nI) 
      m_aListeners[ nI ]->OnDataReceived(pData); 
    } 
} 

的問題是,它迫使我寫一個Trigger方法總是做同樣的事情(迭代,調用處理程序),因爲不同的事件可以有不同的參數列表,並且對於每個事件,相關的處理程序類型具有特定名稱的方法。

我對C++ 11瞭解不多,但我有一種感覺,那就是避免使用模板重寫每種事件類型的Trigger方法。 但我不能使用C++ 11,所以我想知道是否有一種方法,使用較舊的C++版本,以類型安全的方式執行此操作。

編輯:我想過創建一個事件數據類的層次結構,即template< typename ListenerType >::DataDataReceivedEvent::Data : public template< typename ListenerType >::Data,這樣我就可以有一個觸發器方法總是採用一個參數,即virtual void Trigger(const Data * pData)。但我仍然有問題需要在事件監聽器中調用特定的方法。

+0

你可以使用Boost?因爲那樣你可以使用[Boost函數](http://www.boost.org/doc/libs/1_59_0/doc/html/function.html)和[Boost綁定](http://www.boost.org/ doc/libs/1_59_0/libs/bind/doc/html/bind.html)庫。 –

+0

@JoachimPileborg感謝您以前的評論(http://stackoverflow.com/questions/14189440/c-class-member-callback-simple-examples/14189561#14189561)。它似乎在VS2005支持,所以我會看看這個。 而我不想使用增強功能,因爲我的目標平臺是Android(這是正常的)和Windows CE(它不是很好的支持boost)。 – Virus721

+0

Ho不幸的是函數和綁定不支持VS2005 :(但也許我仍然可以找到一個兼容的方式來做到這一點'' – Virus721

回答

0

您也可以使用模板和運算符重載。當你假設ListenerType實現operator()可以實現像這樣(的例子也使用variadic templates您可以使用參數的任意量。):

#include <vector> 
#include <iostream> 

template< typename ListenerType > 
class Event 
{ 
private: 

    std::vector< ListenerType * > m_aListeners; 

public: 

    void operator += (ListenerType * pListener) 
    { 
     m_aListeners.push_back(pListener); 
    } 

    void operator -= (ListenerType * pListener) 
    { 
     auto revIter = m_aListeners.rbegin(); 
     for(; revIter != m_aListeners.rend(); ++revIter) 
      if(revIter == pListener) 
      { 
       m_aListeners.remove(revIter); 
       break; 
      } 
    } 

    template<typename... Params> 
    void operator()(Params... data) { 
     for (auto l : m_aListeners) { 
      (*l)(data...); 
     } 
    } 
}; 

class DataReceivedListener { 
public: 

    void operator()(const char* pData) { 
     std::cout << pData << std::endl; 
    } 

}; 

class DataReceivedEvent : public Event<DataReceivedListener> 
{ 
public: 
}; 


int main() { 

    DataReceivedEvent e; 
    DataReceivedListener l1; 
    DataReceivedListener l2; 
    e += &l1; 
    e += &l2; 

    e("Hello"); 
} 

不幸的是,C++ 11不介紹Concepts。如果你有這個(constraints in C#),你會得到編譯器的更多幫助。

+0

感謝您的幫助!但不幸的是我不能使用C++ 11。 – Virus721

+0

好的。你可以刪除點,它應該與C++ 98一起工作 – Schrieveslaach