之前在学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;
}