C++:用宏实现信号广播功能

之前在学QT的时候,印象最最深刻的就是信号广播功能,这个功能在Ue4中也有;

说白了就设计模式中的观察者模式,将不同的需要通知的函数抽象,最后放到一个类中,当要发送信号到调用这个类的播放功能,当然,要将对应的参数传递进去,然后通过存储的函数指针发送给需要通知的对象;

直接上代码,结构很简单,有大概思路,以后会做优化;

#pragma once

#pragma once


#define BROADCAST(ClassName,ReturnType,...)\
class ClassName{\
    typedef std::function<ReturnType(__VA_ARGS__)> FuType;\
    std::vector<FuType> funs;\
public:\
    void Add(FuType fun) {\
        funs.push_back(fun);\
    }\
    void broadcast(__VA_ARGS__){\

#define FUN_BROADCASTAVG_NAME_LIST(...)\
        for(auto& fun:funs){\
            fun(__VA_ARGS__);\
        }\
    }\
};\

#define BROADCAST_1v(ClassName,ReturnType,avg1Type,avg1Name) \
BROADCAST(ClassName,ReturnType,avg1Type avg1Name)\
FUN_BROADCASTAVG_NAME_LIST(avg1Name)\

#define BROADCAST_2v(ClassName,ReturnType,avg1Type,avg1Name,avg2Type,avgName2) \
BROADCAST(ClassName,ReturnType,avg1Type avg1Name,avg2Type avgName2)\
FUN_BROADCASTAVG_NAME_LIST(avg1Name,avgName2)\


#define BROADCAST_3v(ClassName,ReturnType,avg1Type,avg1Name,avg2Type,avgName2,avg3Type,avgName3) \
BROADCAST(ClassName,ReturnType,avg1Type avg1Name,avg2Type avgName2,avg3Type avgName3)\
FUN_BROADCASTAVG_NAME_LIST(avg1Name,avgName2,avgName3)\


#define BROADCAST_4v(ClassName,ReturnType,avg1Type,avg1Name,avg2Type,avgName2,avg3Type,avgName3,avgType4,avg4Name) \
BROADCAST(ClassName,ReturnType,avg1Type avg1Name,avg2Type avgName2,avg3Type avgName3,avgType4 avg4Name)\
FUN_BROADCASTAVG_NAME_LIST(avg1Name,avgName2,avgName3,avg4Name)\


#define BROADCAST_5v(ClassName,ReturnType,avg1Type,avg1Name,avg2Type,avgName2,avg3Type,avgName3,avgType4,avg4Name,avg5Type,avg5Name) \
BROADCAST(ClassName,ReturnType,avg1Type avg1Name,avg2Type avgName2,avg3Type avgName3,avgType4 avg4Name,avg5Type avg5Name)\
FUN_BROADCASTAVG_NAME_LIST(avg1Name,avgName2,avgName3,avg4Name,avg5Name)\


#define end_____

实现信号功能可能有很多方法,这个方法是模仿ue4中的源码的;

就是利用宏来生成一个类;

最后的功能呢,就是将发送信号的对象和接受信号的对象解耦;

代码是粘贴即用的;

使用格式:宏:BROADCAST_[Integer]v,Integer是参数的个数

宏的第一个参数是ClassName,即类名

第二个参数是被通知对象的方法的的返回类型

下面就是可变多参表了,格式是填写一个参数后加参数变量名,如果是3个参数的宏,那么就要如此写3遍;

下面是使用案例:

#include<iostream>
#include<functional>
#include<string>
#include<vector>
#include<Windows.h>
#include"Broadcast.h"
using namespace std;



BROADCAST_1v(broad, int, int, avg1);
BROADCAST_2v(broad_2v, void, int ,avg1, std::string,avg2);
BROADCAST_3v(broad_3v, void, int ,avg1, std::string,avg2,std::string,avg3);
BROADCAST_4v(broad_4v, void, int ,avg1, std::string,avg2,std::string,avg3,std::function<void(int)>,avg4);
BROADCAST_5v(broad_5v, void, int ,avg1, std::string,avg2,std::string,avg3,std::function<void(int)>,avg4,std::vector<int>,avg5);
 
class testClass {
    int x = 0;
    
public:
    broad broadCast;
    broad_2v broadCast_2v;
    broad_3v broadCast_3v;
    void change() {
        x++;
        
        broadCast_2v.broadcast(x,"broadCast2_v: ");
        broadCast_3v.broadcast(x,"broadCast3_v: ","message");
    }
};

class receive {
public:
    int onChange(int  x,std::string message) {
        std::cout <<message << x << endl;
        return 1;
    }
};

class receive_3v {
public:
    int onChange(int  x, std::string message,std::string message2) {
        std::cout << message << message2 << x << endl;
        return 1;
    }
};


void main() {
    testClass test;
    receive ce1, ce2;
    receive_3v ce1_, ce2_;
    std::function<int(int,std::string)> fun1, fun2;
    fun1 = std::bind(&receive::onChange, &ce1, std::placeholders::_1,std::placeholders::_2);
    fun2 = std::bind(&receive::onChange, &ce2, std::placeholders::_1, std::placeholders::_2);

    std::function<int(int, std::string,std::string)> fun1_, fun2_;
    fun1_ = std::bind(&receive_3v::onChange, &ce1_, std::placeholders::_1, std::placeholders::_2,std::placeholders::_3);
    fun2_ = std::bind(&receive_3v::onChange, &ce2_, std::placeholders::_1, std::placeholders::_2,std::placeholders::_3);


    test.broadCast_2v.Add(fun1);
    test.broadCast_2v.Add(fun2);
    test.broadCast_3v.Add(fun1_);
    test.broadCast_3v.Add(fun2_);
     while (1) {
        Sleep(1000);
        test.change();
    }
    std::function<void(int a, int b)> s;
    int x; cin >> x;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值