[置顶] 编程模仿boost::function和boost::bind
boost::function和boost::bind结合使用是非常强大的,他可以将成员函数和非成员函数绑定对一个对象上,实现了类似C#的委托机制。委托在许多时候可以替代C++里面的继承,实现对象解耦,简单说就是把产生事件的代码和处理事件的代码通过委托者给隔离开来。
但是boost库是非常庞大的,尤其是在发布开源软件时,下载安装boost是一件让用户望而却步的事情。基于此,下面编程模拟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进行测试:
#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)
{
printf("test2\n");
return 0;
}
int test3(int ,char,short)
{
printf("test3\n");
return 0;
}
class TestClass
{
public:
int test0()
{
printf("test obj0\n");
return 0;
}
int test1(int a )
{
printf("test obj1\n");
return 0;
}
int test2(int ,char)
{
printf("test obj2\n");
return 0;
}
int test3(int ,char,short)
{
printf("test obj3\n");
return 0;
}
}; int _tmain(int argc, _TCHAR* argv[])
{
TestClass TestObj; //0个参数测试
printf("0 para test:\n");
bind_base0<int>* t0 = bindfun(test0);
bind_base0<int>* tobj0 = bindfun(&TestObj,&TestClass::test0);
(*t0)();
(*tobj0)();
delete t0;
delete tobj0;
printf("\n"); //1个参数测试
printf("1 para test:\n");
bind_base1<int,int>* t1 = bindfun(test1);
bind_base1<int,int>* tobj1 = bindfun(&TestObj,&TestClass::test1);
(*t1)(12);
(*tobj1)(34);
delete t1;
delete tobj1;
printf("\n"); //2个参数测试
printf("2 para test:\n");
bind_base2<int,int,char>* t2 = bindfun(test2);
bind_base2<int,int,char>* tobj2 = bindfun(&TestObj,&TestClass::test2);
(*t2)(12,77);
(*tobj2)(34,55);
delete t2;
delete tobj2;
printf("\n"); //3个参数测试
printf("3 para test:\n");
bind_base3<int,int,char,short>* t3 = bindfun(test3);
bind_base3<int,int,char,short>* tobj3 = bindfun(&TestObj,&TestClass::test3);
(*t3)(12,77,56);
(*tobj3)(34,55,56);
delete t3;
delete tobj3;
printf("\n"); return 0;
}
测试程序输出结果如下:
[置顶] 编程模仿boost::function和boost::bind的更多相关文章
- 以boost::function和boost:bind取代虚函数
转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...
- boost::function和boost:bind取代虚函数
以boost::function和boost:bind取代虚函数 这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function ...
- boost::function 通过boost::bind调用类成员函数
1. 首先引用boost::function和boost::bind的头文件和库: #include "boost/bind.hpp" #include "boost/f ...
- 关于boost::function与boost::bind函数的使用心得
最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...
- boost::function和boost::bind 介绍
一. boost::function介绍 原文:http://www.cnblogs.com/sld666666/archive/2010/12/16/1907591.html 本片文章主要介绍boo ...
- [置顶] MySQL -- 创建函数(Function
目标 如何在MySQL数据库中创建函数(Function) 语法 CREATE FUNCTION func_name ( [func_parameter] ) //括号是必须的,参数是可选的 RETU ...
- [转] boost::function用法详解
http://blog.csdn.net/benny5609/article/details/2324474 要开始使用 Boost.Function, 就要包含头文件 "boost/fun ...
- boost::function用法详解
要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从 "boost/function/func ...
- boost::function的简单实现
前言 boost::function和boost:bind是一对强大的利器.相信用过的童鞋多少有些体会. 虽然平时在用boost::function,但是用的时候心中总会一些不安,因为不知道它是怎么实 ...
随机推荐
- dedecms的入门使用
前段时间(其实也很远了)一直在学习dedecms,这里对前段时间的学习做一个总结. dedecms学习网址:http://help.dedecms.com/v53
- ThinkPHP第十二天(Import导入第三方类库方法,独立分组文件夹结构)
1.Import(路径+类名,基础路径): 平时导入类时有三种基础路径:Think:import('Think.core.Action');Think表示ThinkPHP/Lib基础路径,完整路径为T ...
- crontab中使用mysql问题
第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 , 并列 - 连续 crontab中不能执行mysql,百分之 ...
- [LeetCode]题解(python):014-Longest Common Prefix
题目来源: https://leetcode.com/problems/longest-common-prefix/ 题意分析: 这道题目是要写一个函数,找出字符串组strs的最长公共前缀子字符串. ...
- python list comprehension twos for loop 嵌套for循环
list comprehension 后面可以有多个for loops,每个for后面可以有if [(x, y, x * y)for x in(0,1,2,3)for y in(0,1,2,3)if ...
- BZOJ 1610: [Usaco2008 Feb]Line连线游戏
1610: [Usaco2008 Feb]Line连线游戏 Description Farmer John最近发明了一个游戏,来考验自命不凡的贝茜.游戏开始的时 候,FJ会给贝茜一块画着N (2 &l ...
- Average(模拟)
Average Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tota ...
- Data Structure(2)
在大体看过一遍<数据结构导论>的基础上完成了上一篇的博客,周五晚上通过上讲课,还是发现了一些问题的,主要体现在对第一章看的比较粗心,第一章的概论其实是对整本书的整体概况,这里没有多看上几遍 ...
- 全局获取Context的技巧
全局获取Context的技巧 在android开发中,非常多地方都要用到Context上下文这个类对象,比方:弹出 Toast 的时候须要.启动活动的时候须要.发送广播的时候须要.操作数据库的时候须要 ...
- eclipse svn2.0.0插件 手动安装方法
org.tigris.subversion.javahl.ClientException: Unsupported working copy formatsvn: This client is too ...