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的更多相关文章

  1. 以boost::function和boost:bind取代虚函数

    转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...

  2. boost::function和boost:bind取代虚函数

    以boost::function和boost:bind取代虚函数 这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function ...

  3. boost::function 通过boost::bind调用类成员函数

    1. 首先引用boost::function和boost::bind的头文件和库: #include "boost/bind.hpp" #include "boost/f ...

  4. 关于boost::function与boost::bind函数的使用心得

    最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...

  5. boost::function和boost::bind 介绍

    一. boost::function介绍 原文:http://www.cnblogs.com/sld666666/archive/2010/12/16/1907591.html 本片文章主要介绍boo ...

  6. [置顶] MySQL -- 创建函数(Function

    目标 如何在MySQL数据库中创建函数(Function) 语法 CREATE FUNCTION func_name ( [func_parameter] ) //括号是必须的,参数是可选的 RETU ...

  7. [转] boost::function用法详解

    http://blog.csdn.net/benny5609/article/details/2324474 要开始使用 Boost.Function, 就要包含头文件 "boost/fun ...

  8. boost::function用法详解

    要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从 "boost/function/func ...

  9. boost::function的简单实现

    前言 boost::function和boost:bind是一对强大的利器.相信用过的童鞋多少有些体会. 虽然平时在用boost::function,但是用的时候心中总会一些不安,因为不知道它是怎么实 ...

随机推荐

  1. 【QT相关】文件、目录基础操作

    判断目录是否存在: QString proFile(t_path); proFile.append("/dir"); QFileInfo proFileInfo(proFile); ...

  2. resolve "Undefined attribute name" warning for Angular "ng-" attributes in HTML files

    由于这些attributes引起的warning数量较多, 影响直观查找其他warning. 因此选择将这类warning忽视掉: Project Property -> Validation ...

  3. 补全aaz288 可能有问题的过程 P_COMPL_AAZ288

    补全aaz288 可能有问题的过程: /* add by weiyongle 20160623 失地农民补足aaz288,针对早期导出的数据(只适用于江安县) 经测试:江安县 江安县个体劳动者 这个单 ...

  4. Android Activity和Intent机制学习笔记

    转自 http://www.cnblogs.com/feisky: Activity Android中,Activity是所有程序的根本,所有程序的流程都运行在Activity之中,Activity具 ...

  5. Yii框架中的CURD操作

    <?php $Admin = new Admin(); //查找多条记录,返回二维数组 $Admin->findAll(); $Admin->findAll("id = 2 ...

  6. Google浏览器的缓存文件过大(mega网站导致的)

    到选项里清空所有内容也没有用. 后来手动找了一下,原来在这里,存了在这里存了整整10G的缓存: C:\Users\my\AppData\Local\Google\Chrome\User Data\Pr ...

  7. Android EditText 无法换行

    问题 关于控制是否换行的属性android:singleLine 当值为true的时候,只能一行,不换行 当值为false的时候,可以换行 但是现在遇到一个问题: <EditText andro ...

  8. Xamarin.Android开发实践(五)

    原文:Xamarin.Android开发实践(五) 一.服务的生命周期 服务与活动一样,在它的整个生命周期中存在着一些事件,下图可以很好解释整个过程以及涉及到的方法: 在真实的使用中,Service来 ...

  9. python爬虫实战1

    转载于:http://blog.csdn.net/dongnanyanhai/article/details/5552431 首先推荐一个网站:中医世家,这个网站上有很多关于中医的资料,光是提供的中医 ...

  10. cocos2dx进阶学习之屏幕适配

    背景 在学习cocos2dx时,我们在main函数中发现一句代码, #include "main.h" #include "AppDelegate.h" #in ...