编程模仿boost::function和boost::bind
boost::function和boost::bind结合使用是非常强大的,他可以将成员函数和非成员函数绑定对一个对象上,实现了类似C#的委托机制。委托在许多时候可以替代C++里面的继承,实现对象解耦,简单说就是把产生事件的代码和处理事件的代码通过委托者给隔离开来。但是boost库是非常庞大的,尤其是在发布开源软件时,下载安易做图oost是一件让用户望而却步的事情。基于此,下面编程模拟boost::function和boost::bind。
为了满足90%以上的应用场合,该代码实现以下目标:
1.支持成员函数和非成员函数绑定。
2.支持多个参数(最多9个),代码中使用#define宏定义了1到9个参数的版本。
3.为了在大规模应用中多次分配function对象造成内存碎片,对new和delete进行重载,方便使用内存池管理内存。
下面贴出代码:
/*
* Author: chzuping
* Email: chzuping@gmail.com
* description: 模拟boost::bind和boost::function
*/
#pragma once;
#ifndef ZWBIND_MALLOC
#define ZWBIND_MALLOC malloc
#endif
#ifndef ZWBIND_FREE
#define ZWBIND_FREE free
#endif
namespace ZwBind
{
class bind_base
{
public:
static void *operator new(size_t size )
{
return ZWBIND_MALLOC(size);
}
static void operator delete( void *ptr)
{
ZWBIND_FREE(ptr);
}
};
template<class ret_type>
class bind_base0:public bind_base
{
public:
virtual ret_type callfun() = 0;
ret_type operator()()
{
return callfun();
}
};
template<class ret_type, class obj_type>
class bindobj0 : public bind_base0<ret_type>
{
public:
bindobj0(obj_type* pobject, ret_type (obj_type::*pmemfun)())
{
m_pobject = pobject;
m_pmemfun = pmemfun;
}
virtual int callfun()
{
return (m_pobject->*m_pmemfun)();
}
private:
obj_type* m_pobject;
ret_type (obj_type::* m_pmemfun)();
};
template<class ret_type>
class bind0 : public bind_base0<ret_type>
{
public:
bind0( ret_type (*pfun)())
{
m_pfun = pfun;
}
virtual ret_type callfun()
{
return m_pfun();
}
private:
ret_type (*m_pfun)();
};
template<class ret_type, class obj_type>
bindobj0<ret_type,obj_type>* bindfun(obj_type* pclass, ret_type (obj_type::*pmemfun)())
{
void *pRet = NULL;
bindobj0<ret_type,obj_type>* pbind = new bindobj0<ret_type,obj_type>(pclass, pmemfun);
return pbind;
}
template<class ret_type>
bind0<ret_type>* bindfun(ret_type (*pmemfun)())
{
bind0<ret_type>* pbind = new bind0<ret_type>(pmemfun);
return pbind;
}
#define DECLARE_PARAMS(...) __VA_ARGS__
#define DECLARE_TPYE(...) __VA_ARGS__
#define DECLARE_ARGS(...) __VA_ARGS__
#define DECLARE_VAR(...) __VA_ARGS__
#define DECLARE_SIGSLOT(index, ptype,classparam,args,var) \
template<class ret_type,classparam>\
class bind_base##index\
{\
public:\
virtual ret_type callfun(args) = 0;\
ret_type operator()(args)\
{\
return callfun(var);\
}\
};\
template<class ret_type,class obj_type, classparam> \
class bindobj##index:public bind_base##index<ret_type,ptype>\
{\
public:\
bindobj##index(obj_type* pobject, ret_type (obj_type::*pmemfun)(args))\
{\
m_pobject = pobject;\
m_pmemfun = pmemfun;\
}\
virtual ret_type callfun(args)\
{\
return (m_pobject->*m_pmemfun)(var);\
}\
private:\
obj_type* m_pobject;\
ret_type (obj_type::* m_pmemfun)(args);\
};\
template<class ret_type,classparam>\
class bind##index : public bind_base##index<ret_type,ptype>\
{\
public:\
bind##index(ret_type (*pfun)(args))\
{\
m_pfun = pfun;\
}\
virtual ret_type callfun(args)\
{\
return m_pfun(var);\
}\
private:\
ret_type (*m_pfun)(args);\
};\
template<class ret_type,class obj_type, classparam> \
bindobj##index<ret_type,obj_type,ptype>* bindfun(obj_type* pclass, ret_type (obj_type::*pmemfun)(args))\
{\
void *pRet = NULL;\
bindobj##index<ret_type,obj_type,ptype>* pbind = new bindobj##index<ret_type,obj_type,ptype>(pclass, pmemfun);\
return pbind;\
}\
template<class ret_type,classparam>\
bind##index<ret_type,ptype>* bindfun(ret_type (*pmemfun)(args))\
{\
bind##index<ret_type,ptype>* pbind = new bind##index<ret_type,ptype>(pmemfun);\
return pbind;\
}
DECLARE_SIGSLOT(1,DECLARE_PARAMS(arg1_type), DECLARE_TPYE(class arg1_type),DECLARE_ARGS(arg1_type a1),DECLARE_VAR(a1));
DECLARE_SIGSLOT(2,DECLARE_PARAMS(arg1_type,arg2_type), DECLARE_TPYE(class arg1_type,class arg2_type),DECLARE_ARGS(arg1_type a1, arg2_type a2),DECLARE_VAR( a1, a2));
DECLARE_SIGSLOT(3,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3),DECLARE_VAR( a1,a2,a3));
DECLARE_SIGSLOT(4,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4),DECLARE_VAR( a1,a2,a3,a4));
DECLARE_SIGSLOT(5,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type,arg5_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type,class arg5_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5),DECLARE_VAR( a1,a2,a3,a4,a5));
DECLARE_SIGSLOT(6,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type,arg5_type,arg6_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type,class arg5_type,class arg6_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6),DECLARE_VAR( a1,a2,a3,a4,a5,a6));
DECLARE_SIGSLOT(7,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type,arg5_type,arg6_type,arg7_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type,class arg5_type,class arg6_type,class arg7_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7),DECLARE_VAR( a1,a2,a3,a4,a5,a6,a7));
DECLARE_SIGSLOT(8,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type,arg5_type,arg6_type,arg7_type,arg8_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type,class arg5_type,class arg6_type,class arg7_type,class arg8_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8),DECLARE_VAR( a1,a2,a3,a4,a5,a6,a7,a8));
DECLARE_SIGSLOT(9,DECLARE_PARAMS(arg1_type,arg2_type,arg3_type,arg4_type,arg5_type,arg6_type,arg7_type,arg8_type,arg9_type), DECLARE_TPYE(class arg1_type,class arg2_type,class arg3_type,class arg4_type,class arg5_type,class arg6_type,class arg7_type,class arg8_type,class arg9_type),DECLARE_ARGS(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8, arg9_type a9),DECLARE_VAR( a1,a2,a3,a4,a5,a6,a7,a8,a9));
};
using namespace ZwBind;
在下面测试代码中,对0到3个参数的bind进行测试:
[cpp] view plaincopy
#include "stdafx.h"
#include <malloc.h>
#include "ZwBind.h"
int test0()
{
printf("test0\n");
return 0;
}
int test1(int a )
{
printf("test1\n");
return 0;
}
int test2(int ,char)
{补充:软件开发 , C++ ,
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊