C++实现UE委托

7 篇文章 0 订阅
#include<iostream>
#include<vector>
#include "Functional"

/**
 * 所涉及的知识点:
 * (1)typedef的函数指针定义方式
 * (2)Using的函数指针定义方式
 * (3)单播绑定和执行的过程(C++仿照UE)
 * (4)Function的使用——bind以及对这种包装器(std::function<void(int, int)> )的使用
 * (5)多播的实现(Fdelegate的类中的private变量用Vector保存函数包装器)
 * (6)使用宏编程的方式
 * (7)使用模板方式定义委托(避免重复写委托类)、
 * (8)可变参数的使用
 */

/* 普通版本

 //使用typedef方式对函数指针的定义
typedef void(*FunMethod)(int, int);
using FuncMethod1 = int(*)(int, int);

class TestA
{
public:
	void LessNum(int a, int b)
	{
		const int c = a - b;
		std::cout << "a - b = " << c << std::endl;
	}
	void LessNum1(int a, int b)
	{
		const int c = b - a;
		std::cout << "b - a = " << c << std::endl;
	}

};

typedef void(TestA::* LessFunMethod)(int, int);
using LessFunMethod1 = int(TestA::*)(int, int);

class FDelegateTwoParams
{
public:
	//绑定的是一个全局方法
	void BindRaw(FunMethod FunPtr, int a, int b)
	{
		FunArray.push_back(std::bind(FunPtr, a, b));
	}

	//绑定一个类的成员方法
	void BindRaw2(TestA* UserClass, LessFunMethod FunPtr, int a, int b)
	{
		FunArray.push_back(std::bind(FunPtr, UserClass, a, b));
	}

	void BindStatic()
	{
	}

	bool IsBound()const
	{
		return !FunArray.empty() ? true : false;
	}

	void Excute()
	{
		for (auto Fun : FunArray)
		{
			Fun(0, 0);
		}

	}

	void Broadcast()
	{
		for (auto Fun : FunArray)
		{
			Fun(0, 0);
		}
	}
	bool ExcuteIfBound()
	{
		if (IsBound())
		{
			Excute();
			return true;
		}
		return false;
	}

private:
	std::vector<std::function<void(int, int)>> FunArray;
};

void AddNum(int a, int b)
{
	const int c = a + b;
	std::cout << "a + b = " << c << std::endl;
}

int main()
{
	//(1)typedef的函数指针定义方式
	FunMethod fun1 = &AddNum;
	fun1(5, 7);

	// 单播测试绑定全局函数
	
	//FDelegateTwoParams Delegate;
	//Delegate.BindRaw(&AddNum, 5, 8);
	//Delegate.Excute();
	
	// 单播测试绑定其他类的成员函数(加入多播多播的Vector设置)
	FDelegateTwoParams Delegate;
	TestA* UserClass = new TestA();
	Delegate.BindRaw2(UserClass, &TestA::LessNum, 100, 10);
	Delegate.BindRaw(&AddNum, 100, 10);
	Delegate.Broadcast();

	system("pause");
}
*/


/**
 * 宏编程版本
 */

class TestA
{
public:
	void FunNoparam()
	{
		std::cout << "Hello Delegate"<<std::endl;
	};

	void FunTwoParam(int a, int b)
	{
		std::cout << "a + b = " << a + b << std::endl;
	}
};

// 函数指针的两种定义方式
typedef void (*FunMethodNoParam1)(void);
using FunMethodNoParam = void(TestA::*)(void);

// 无参数单播委托
#define DECLARE_DELEGATE(DelegateName)\
class F##DelegateName\
{\
public:\
	void BindRaw2(TestA * UserClass, FunMethodNoParam FunPtr)\
	{\
		Fun = std::bind(FunPtr, UserClass); \
	}\
	bool IsBound()\
	{\
		return Fun ? true : false; \
	}\
	void Excute()\
	{\
		Fun(); \
	}\
	bool ExcuteIfBound()\
	{\
		if (IsBound())\
		{\
			Excute(); \
			return true; \
		}\
		return false; \
	}\
private:\
	std::function<void()> Fun; \
};


// 函数指针的两种定义方式
typedef void (TestA::* FunMethodTwoParam1)(int, int);
using FunMethodTwoParam = void(TestA::*)(int, int);

// 两个参数的单播委托
#define DECLARE_DELEGATE_TwoParams(DelegateName, ParamType1, ParamType2)\
class F##DelegateName\
{\
public:\
	void BindRaw2(TestA * UserClass, FunMethodTwoParam FunPtr, ParamType1 t1, ParamType2 t2)\
	{\
		Fun = std::bind(FunPtr, UserClass, t1, t2); \
	}\
	bool IsBound()\
	{\
		return Fun ? true : false; \
	}\
	void Excute()\
	{\
		Fun(); \
	}\
	bool ExcuteIfBound()\
	{\
		if (IsBound())\
		{\
			Excute(); \
			return true; \
		}\
		return false; \
	}\
private:\
	std::function<void()> Fun; \
};

// 对于单播来说,后面的;可以加,也可以不加,因为在宏定义中已经有了
// 委托的声明

DECLARE_DELEGATE(TestDelegateNoParam);
DECLARE_DELEGATE_TwoParams(TestDelegateTwoParam, int, int);

//int main()
//{
//	// 注意前面要加上F,因为宏的定义
//	FTestDelegateNoParam Delegate;
//	TestA* ObjPtr = new TestA;
//	Delegate.BindRaw2(ObjPtr, &TestA::FunNoparam);
//	Delegate.Excute();
//	system("pause");
//}



/**
 * 模板编程版本
 */
template<typename Class,typename RetType,typename...ArgTypes>
struct TMemFunPtrType
{
	typedef RetType(Class::* Type)(ArgTypes...);
};

template<typename RetValType,typename... ParamTypes>
class TBaseDelegate
{
public:
	template<typename UserClass, typename... Types>
	void BindRaw(UserClass* MyUserClass,
		typename TMemFunPtrType<UserClass, RetValType, Types...>::Type FunPtr, Types... Vars)
	{
		Fun = std::bind(FunPtr, MyUserClass, Vars...);
	}
	bool IsBound()
	{
		return Fun ? true : false;
	}

	void Excute()
	{
		Fun();
	}

	bool ExcuteIfBound()
	{
		if (IsBound())
		{
			Excute();
			return true;
		}
		return false;
	}

private:
	std::function<RetValType()>Fun;
};

// 单播无参数
#define DECLARE_DELEGATE(DelegateName) \
class DelegateName : public TBaseDelegate<void>{};
#define DECLARE_DELEGATE_TwoParam(DelegateName,ParamType1,ParamType2)\
class DelegateName : public TBaseDelegate<void, ParamType1, ParamType2>{};
#define DECLARE_DELEGATE_RetVal_TwoParam(RetType,DelegateName,ParamType1,ParamType2)\
class DelegateName : public TBaseDelegate<RetType, ParamType1, ParamType2>{};

DECLARE_DELEGATE(TestDelegateNameNoParam);
DECLARE_DELEGATE_TwoParam(TestDelegateTwoParam, int, int);
DECLARE_DELEGATE_RetVal_TwoParam(int, TestDelegateTwoParamRet, int, int);

class TestB
{
public:
	void T()
	{
		std::cout << "Hello World !!!" << std::endl;
	}

	void TA(int a, int b)
	{
		std::cout << "a + b = " << a + b << std::endl;
	}
	int Minus(int c, int d)
	{
		std::cout << "c - d : " << std::endl;
		return c - d;
	}
};

 int main()
 {
	 TestDelegateNameNoParam TDelegate;
	 TestB ObjPtr;
	 TDelegate.BindRaw(&ObjPtr, &TestB::T);
	 TDelegate.Excute();

	 TestDelegateTwoParam Delegate;
	 Delegate.BindRaw(&ObjPtr, &TestB::TA, 90, 10);
	 Delegate.Excute();

	 TestDelegateTwoParamRet DelegateRet;
	 DelegateRet.BindRaw(&ObjPtr, &TestB::Minus, 100, 10);
	 DelegateRet.Excute();
	 system("pause");
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值