前言
之前我们有写过以及封装过代理,但是不够完善,我们要在此基础上进行完善
这个是以前我们封装的代理点击跳转
基础封装
FDelegateBase :是所以代理的基类,只有一个Execute 执行方法
template<typename TReturn, typename ...InParams>
class FDelegateBase
{
public:
virtual TReturn Execute(InParams &&...Params)
{
return TReturn();
}
};
FObjectDelegate :用于成员函数代理
template<typename TObjectInstance, typename TReturn, typename ...InParams>
class FObjectDelegate : public FDelegateBase<TReturn, InParams...>
{
public:
FObjectDelegate(TObjectInstance* InInstance, TReturn(TObjectInstance::* InFunction)(InParams...))
:ObjectInstance(InInstance), InstanceFunction(InFunction)
{
}
virtual TReturn Execute(InParams &&...Params) override
{
return (ObjectInstance->*InstanceFunction)(forward<InParams>(Params)...);
}
TObjectInstance* ObjectInstance;
TReturn(TObjectInstance::* InstanceFunction)(InParams...);
};
FFunctionDelegate :用于非成员函数代理
template<typename TReturn, typename ...InParams>
class FFunctionDelegate : public FDelegateBase<TReturn, InParams...>
{
public:
FFunctionDelegate(TReturn(*InFunction)(InParams...))
:Function(InFunction)
{
}
virtual TReturn Execute(InParams &&...Params) override
{
return (*Function)(forward<InParams>(Params)...);
}
TReturn(*Function)(InParams...);
};
FDelegate 是真实要创建代理的类,其中提供了绑定、解绑、创建代理的方法
之后我们的单播和多播只需要继承此类即可
template<typename TReturn, typename ...InParams>
class FDelegate
{
public:
FDelegate()
: Ptr(nullptr)
{
}
template<typename TObjectInstance>
void Bind(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
{
ResetPtr();
Ptr = new FObjectDelegate<TObjectInstance, TReturn, InParams...>(InObjectInstance, InObjectFunction);
}
void Bind(TReturn(*InObjectFunction)(InParams...))
{
ResetPtr();
Ptr = new FFunctionDelegate<TReturn, InParams...>(InObjectFunction);
}
void UnBind()
{
ResetPtr();
}
TReturn Execute(InParams &&...Params)
{
if (Ptr)
{
return Ptr->Execute(forward<InParams>(Params)...);
}
return TReturn();
}
template<typename TObjectInstance>
static FDelegate<TReturn, InParams...> Create(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
{
FDelegate<TReturn, InParams...> del;
del.Bind(InObjectInstance, InObjectFunction);
return del;
}
static FDelegate<TReturn, InParams...> Create(TReturn(*InObjectFunction)(InParams...))
{
FDelegate<TReturn, InParams...> del;
del.Bind(InObjectFunction);
return del;
}
private:
void ResetPtr()
{
if (Ptr)
{
delete Ptr;
Ptr = nullptr;
}
}
private:
FDelegateBase<TReturn, InParams...>* Ptr;
};
完善单播
我们继承之前的基类
template<typename TReturn,typename ...InParams>
class FSingleDelegate : public FDelegate<TReturn, InParams...>
{
public:
FSingleDelegate():FDelegate<TReturn, InParams...>()
{
}
};
可以如下使用
auto Del = FDelegate<int, int, int>::Create([](int a, int b)->int
{
return a + b;
});
int ret = Del.Execute(1, 2);
cout << ret << endl;
Del.UnBind();
为了我们更方便的使用我们可以包裹成为宏
#define SIMPLE_SINGLE_DELEGATE(Name,Return,...) FSingleDelegate<Return,__VA_ARGS__> Name
SIMPLE_SINGLE_DELEGATE(TestDelegate, int, int, int);
TestDelegate.Bind([](int a, int b)->int
{
return a + b;
});
int Ret1 = TestDelegate.Execute(2, 3);
cout << Ret1 << endl;
TestDelegate.UnBind();
但是我们为了更贴近UE的方式,所以使用类似的定义方式
#define DEFINE_SIMPLE_SINGLE_DELEGATE(Name,Return,...) class Name : public FSingleDelegate<Return,__VA_ARGS__>{}
之后我们声明
DEFINE_SIMPLE_SINGLE_DELEGATE(MyTestDelegate, int, int, int);
如下的使用方式简介清晰了很多
MyTestDelegate TestDel;
TestDel.Bind([](int a, int b)->int
{
return a + b;
});
int Ret2 = TestDel.Execute(3, 4);
cout << Ret2 << endl;
TestDel.UnBind();
完善多播
有了上面单播的例子,我们多播只需要一个容器来存储多个即可,所以我们使用Map容器(为了之后能对某一个函数进行移除操作)
#include <map>
typedef void* DelegateHandle;
template<typename TReturn, typename ...InParams>
class FMulDelegate : public std::map<DelegateHandle,FDelegate<TReturn, InParams...>>
{
typedef FDelegate<TReturn, InParams...> DelegateType;
public:
FMulDelegate()
{
}
template<typename TObjectInstance>
DelegateHandle Bind(TObjectInstance* InObjectInstance, TReturn(TObjectInstance::* InObjectFunction)(InParams...))
{
DelegateHandle Handle = reinterpret_cast<void*&>(InObjectFunction);
this->insert(make_pair(Handle,DelegateType()));
DelegateType& Del =(*this)[Handle];
Del.Bind(InObjectInstance, InObjectFunction);
return nullptr;
}
DelegateHandle Bind(TReturn(*InObjectFunction)(InParams...))
{
DelegateHandle Handle = InObjectFunction;
this->insert(make_pair(Handle, DelegateType()));
DelegateType& Del = (*this)[Handle];
Del.Bind(InObjectFunction);
return Handle;
}
void Broadcast(InParams &&...Params)
{
for (auto& item : *this)
{
item.second.Execute(forward<InParams>(Params)...);
}
}
void UnBind(DelegateHandle Handle)
{
DelegateType& Del = (*this)[Handle];
Del.UnBind();
this->erase(Handle);
}
void UnBindAll()
{
for (auto& item : *this)
{
item.second.UnBind();
}
this->clear();
}
};
#define DEFINE_SIMPLE_MUL_DELEGATE(Name,...) class Name : public FMulDelegate<void,__VA_ARGS__>{}
DEFINE_SIMPLE_MUL_DELEGATE(MyTestMulDelegate, int, int);
使用:
struct FMyStruct
{
void TestFunc(int a, int b)
{
cout << a * b << endl;
}
};
MyTestMulDelegate TestMulDel;
DelegateHandle h1 = TestMulDel.Bind([](int a1, int a2)
{
cout << a1 + a2 << endl;
});
FMyStruct myStruct;
TestMulDel.Bind(&myStruct, &FMyStruct::TestFunc);
TestMulDel.UnBind(h1);
TestMulDel.Broadcast(2, 3);
TestMulDel.UnBindAll();