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;
 
}

猜你喜欢

转载自blog.csdn.net/qq_35718950/article/details/84031368