C++ 实现委托

委托简单的理解就是把函数(成员函数、全局函数或静态函数)指针封装成一个仿函数类,

这样做的好处有:

1、解耦函数实现和调用(函数的调用者不知道函数的实现者)

2、加强类型安全性(函数指针是一个内存指针,委托是一个类)

3、作为参数传递(替换回调函数)

c++ 标准库并没有实现委托的功能,C++98/03 实现起来比较困难(可以参考fastDelegate),C++11之后有了可变模板参数后,实现起来相对容易了,以下是C++11实现委托的代码:

#pragma once

/**********************************
* file: delegate.h
* author: vison0300@163.com
* date:2018-11-23
**********************************/

namespace dlgt
{
	template<typename TReturn, typename...TArgs>
	class TDelegate
	{
		typedef TReturn return_type;

		struct IBaseFunction
	    {
			virtual return_type operator()(TArgs... args) = 0;
        };

		template <typename TClass>
		class TMemberFunction : public IBaseFunction
		{
		public:
			typedef TClass class_type;
			typedef return_type(class_type::*function_type)(TArgs...);

			explicit TMemberFunction(class_type* pObj, function_type pFunc)
			{
				m_pObj = pObj;
				m_pFunc = pFunc;
			}

			virtual return_type operator()(TArgs... args)
			{
				return (m_pObj->*m_pFunc)(args...);
			}

		private:
			class_type* m_pObj;
			function_type m_pFunc;
		};

		class CStaticFunction : public IBaseFunction
		{
		public:
			typedef return_type(*function_type)(TArgs...);

			explicit CStaticFunction(function_type pFunc)
			{
				m_pFunc = pFunc;
			}

			virtual return_type operator()(TArgs... args)
			{
				return (*m_pFunc)(args...);
			}

		public:
			function_type m_pFunc;
		};

		IBaseFunction* m_pBaseFunc;

		void clear()
		{
			if (m_pBaseFunc)
			{
				delete m_pBaseFunc;
				m_pBaseFunc = nullptr;
			}
		}

	public:
		TDelegate()
		{
			m_pBaseFunc = nullptr;
		}

		template<typename TClass>
		explicit TDelegate(TClass* pObj, typename TMemberFunction<TClass>::function_type pFunc)
		{
			bind(pObj, pFunc);
		}

		explicit TDelegate(typename CStaticFunction::function_type pFunc)
		{
			bind(pFunc);
		}

		~TDelegate()
		{
			clear();
		}

		template<typename TClass>
		void bind(TClass* pObj, typename TMemberFunction<TClass>::function_type pFunc)
		{
			clear();
			m_pBaseFunc = new TMemberFunction<TClass>(pObj, pFunc);
		}

		void bind(typename CStaticFunction::function_type pFunc)
		{
			clear();
			m_pBaseFunc = new CStaticFunction(pFunc);
		}

		return_type operator()(TArgs... args)
		{
			return (*m_pBaseFunc)(args...);
		}
	};
}

 

测试代码:


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

class CMath
{
public:
	int Add(int a, int b)
	{
		std::cout << "CMath::Add(" << a << "," << b << ") = " << a + b << "\r\n";
		return a + b;
	}

	void Test()
	{
		std::cout << "CMath::Test()" << "\r\n";
	}
};

int add(int a, int b)
{
	std::cout << "add(" << a << "," << b << ") = " << a + b << "\r\n";
	return a + b;
}

int main()
{

	dlgt::TDelegate<int, int, int> d1(add);
	d1(1, 2);

	CMath m;
	d1.bind(&m, &CMath::Add);
	d1(3, 4);

	dlgt::TDelegate<void> d2(&m, &CMath::Test);
	d2();

	getchar();
    return 0;
}

 

输出结果:

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值