[置顶] 编程模仿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,但是用的时候心中总会一些不安,因为不知道它是怎么实 ...
随机推荐
- FFTW程序Demo
#include<stdio.h> #include<stdlib.h> #include <fftw3.h> #include<string.h> # ...
- [C/C++基础]读写文件
1.打开.关闭文件: FILE* fp = fopen(string.c_str(), FLAG); string.c_str():需用C语言字符串形式: FLAG说明: r: 只读方式打开: w: ...
- 设计模式值六大原则——开闭原则(OCP)
开闭原则(Open Closed Principle)是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的.灵活的系统. 定义: 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. S ...
- 如何在Eclipse中配置Tomcat(免安装版)
如何在Eclipse中配置Tomcat(免安装版) 2013-10-09 23:19wgelgrsh | 分类:JAVA相关 | 浏览642次 分享到: 2013-10-10 17:10提问者采纳 ...
- linux下面安装软件学习流程
先不要急着配置LNMP 我相信你的LINUX基础一定很差,先去学LINUX. 基础最重要. 凡事都要先从基础搞起. 再把gcc搞搞. gcc的相关参数很多,多了解一下. 想要编译安装,不对gcc有些了 ...
- 基于QtQuick2.0应用程序运行于XP系统的诸多问题
客户端 使用QtQuick技术开发酷炫的XP客户端经常遇到白屏或者无界面 if Qt is built using ANGLE, its shared libraries and the requir ...
- HTML::Entities 编码或解码 HTML 实体的字符串
<pre name="code" class="html"><pre name="code" class="py ...
- 国外稳定的免费PHP空间byethost.com
byethost.com是一个老牌的免费空间商,从2006年起就開始提供免费空间了,其免费服务很稳定(看完下文你就知道有多稳定了). 提供5.5G的免费空间,200G的月流量,能够绑定50个域名,也能 ...
- Jquery获对HTML控件的控制
Jquery获对HTML控件的控制 1.获取控件的值 1.1.radio 1.1.1 获取一组radio被选中项的值 var item = $('input[name=items][checked] ...
- CodeForces 508C Anya and Ghosts 贪心
做不出题目,只能怪自己不认真 题目: Click here 题意: 给你3个数m,t,r分别表示鬼的数量,每只蜡烛持续燃烧的时间,每个鬼来时要至少亮着的蜡烛数量,接下来m个数分别表示每个鬼来的时间点( ...