c++ 实现 Qt 信号槽机制

来自 https://gitee.com/jiang_xu_hui/tan-meta-object

TanMetaObject

介绍

80行代码实现Qt信号槽机制。
去除无用行估计也就40行。

使用说明
  1. 仿Qt的信号槽,本来打算用c++20的概念和约束来写,但是国内根本没有普及c++20,最后还是用了c++11.
  2. main.cpp内有使用的例子。

TanMetaObject.h

#include <vector>
#include <utility>

template<typename T, typename ...Args>
using signal_function = void(T::*)(Args...);

template <typename ...Args>
struct TanSlotBase
{
    virtual void run(Args...) = 0;
};

template<typename T, typename ...Args>
class TanSlot : public TanSlotBase<Args...>
{
public:
    TanSlot(T* class_ptr, signal_function<T, Args...> slot_func_ptr)
        : class_ptr(class_ptr), slot_func_ptr(slot_func_ptr){}

    bool operator==(T* ptr)
    {
        return class_ptr == ptr;
    }
    bool operator==(signal_function<T, Args...> func)
    {
        return slot_func_ptr == func;
    }
private:
    virtual void run(Args... args) final
    {
        (class_ptr->*slot_func_ptr)(args...);
    }

private:
    T* class_ptr;
    signal_function<T, Args...> slot_func_ptr;
};

template< typename...Args>
class TanSignal
{
public:
    using slot_func = void(*)(Args...);
public:
    std::vector<TanSlotBase<Args...>*> _slots;
    
    void emit(Args... args)
    {
        for(auto slot : _slots)
        {
            slot->run(args...);
        }
    }
    ~TanSignal(){
        for(auto slot : _slots)
        {
            delete slot;
        }
    }
};

template<typename SIGNAL, typename CONTEXT,typename ...Args>
void connect(SIGNAL* signal, CONTEXT* context, signal_function<CONTEXT, Args...> slot)
{
    signal->_slots.push_back(new TanSlot<CONTEXT, Args...>(context, slot));
}

template<typename SIGNAL, typename CONTEXT,typename ...Args>
void disconnect(SIGNAL* signal, CONTEXT* context, signal_function<CONTEXT, Args...> slot)
{
    for(auto iter = signal->_slots.begin(); iter != signal->_slots.end(); iter++)
    {
        TanSlot<CONTEXT, Args...>* p_slot = (TanSlot<CONTEXT, Args...>*)*iter;
        if(*p_slot == context && *p_slot == slot)
        {
            delete p_slot;
            signal->_slots.erase(iter);
            break;
        }
    }
}

main.cpp

#include "TanMetaObject.h"
#include <iostream>

class A
{
public:
    TanSignal<int, const char*> signal;

    void function(int a, const char* str){
        printf("function slot:%d, %s\n", a, str);
    }
};

class B
{
public:
    void function1(int a, const char* str){
        printf("class B slot:%d, %s\n", a, str);
    }
};

class C
{
public:
    void function2(int a, const char* str){
        printf("class C slot:%d, %s\n", a, str);
    }
};

int main(void)
{
    A a; B b; C c;
    connect(&a.signal, &a, &A::function);
    connect(&a.signal, &b, &B::function1);
    connect(&a.signal, &c, &C::function2);
    a.signal.emit(111, "123");

    printf("**********\n");

    disconnect(&a.signal, &c, &C::function2);
    a.signal.emit(123, "abc");

    return 0;
}
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值