1. 程式人生 > >C++實現訊號和槽機制

C++實現訊號和槽機制

主要通過,C++實現型別QT訊號和槽的問題

設計思路:
1、利於模板函式和模板類的通用性
2、bind的時候,將槽函式指標儲存,觸發時呼叫
程式碼如下:

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
 
#define Connect(sender, signal, receiver, method) ((sender)->signal.Bind(receiver, method))
/*
* func: 槽函式基類
* parm:
* return:
*/
template<class T>
class SlotBase
{
public:
    virtual void Exec(T param1) = 0;  //純虛擬函式
    virtual ~SlotBase(){}
};
 
 
/*
* func: 槽函式
* parm:
* return:
*/
template<class T, class T1>
class Slot : public SlotBase<T1>
{
public:
 
    /* 定義Slot的時候,獲取槽函式資訊 */
    Slot(T* pObj, void (T::*func)(T1))
    {
        m_pSlotBase = pObj;
        m_Func = func;
    }
 
    /* signal觸發時,呼叫 */
    void Exec(T1 param1)
    {
        (m_pSlotBase->*m_Func)(param1);
    }
 
private:
    /* 槽函式資訊 暫存 */
    T* m_pSlotBase = NULL;
    void (T::*m_Func)(T1);
};
 
/*
* func: 訊號
* parm:
* return:
*/
template<class T1>
class Signal
{
public:
 
    /* 模板函式 -> Bind時獲取槽函式指標 */
    template<class T>
    void Bind(T* pObj, void (T::*func)(T1))
    {
        m_pSlotSet.push_back(new Slot<T,T1>(pObj,func));
    }
 
    /* 過載操作符 -> signal觸發機制 */
    void operator()(T1 param1)
    {
        for(int i=0;i<(int)m_pSlotSet.size();i++)
        {
            m_pSlotSet[i]->Exec(param1);
        }
    }
 
    ~Signal()
    {
        for(int i=0;i<(int)m_pSlotSet.size();i++)
        {
            delete m_pSlotSet[i];
        }
    }
 
private:
    vector<SlotBase<T1>*> m_pSlotSet; //這一句很重要,靠基類的指標來儲存 訊號槽指標
};
 
 
 
 
class TestFunc1
{
public:
    void FuncOfA(int parm)
    {
        printf("enter FuncOfA parm = %d\n", parm);
    }
};
class TestFunc2
{
public:
    void FuncOfB(int parm)
    {
        printf("enter FuncOfB parm = %d\n", parm);
    }
};
 
 
class TestSignal
{
public:
    TestSignal()
    {
    }
    void emit(int value)
    {
        ValueChanged(value);
    }
 
public:
    Signal<int> ValueChanged;
 
 
};
 
int main()
{
    /* 1、定義訊號和槽 */
    TestFunc1* pFunc1 = new TestFunc1;
    TestFunc2* pFunc2 = new TestFunc2;
    TestSignal* pSignal = new TestSignal;
 
    /* 2、1個訊號繫結2個槽 */
    Connect(pSignal, ValueChanged, pFunc1, &TestFunc1::FuncOfA);
    Connect(pSignal, ValueChanged, pFunc2, &TestFunc2::FuncOfB);
 
    /* 3、觸發訊號 */
    pSignal->emit(1);
    pSignal->emit(2);
 
 
 
    delete pFunc1;
    delete pFunc2;
    delete pSignal;
 
}