[置顶] 编程模仿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,但是用的时候心中总会一些不安,因为不知道它是怎么实 ...
随机推荐
- MySQL支持emoji
方案1: 应用层支持 MySQL默认的数据库编码是utf8,对于emoji文字是不能直接存储的,要想存储emoji,有许多库支持对emoji的转换,例如将
- 去掉word2007回车后自动编号
1. 在使用word自动编号时,回车续写上一编号内容可能会行距很宽,这时候使用shift+回车不会自动下一编号,而且是正常行距 取消回车自动编号: 打开Word文档,单击菜单栏上的[格式]→[自动套用 ...
- C++对C语言的非面向对象特性扩充(2)
上一篇随笔写了关于C++在注释,输入输出,局部变量说明的扩充,以及const修饰符与C中的#define的比较,也得到了几位学习C++朋友们的帮助讲解,十分感谢,我也希望欢迎有更多学习C++的朋友一起 ...
- CSS——图片替换方法比较
图片替换主要是指将文字替换成图片的技术,即在html语句中使用文字,浏览器显示时用对应的图片显示.其意义在于便于做网站优化(SEO),文字才是搜索引擎寻找的主要对象. 经典的替换方法: Fahrner ...
- Python学习之路——字符处理(二)
一.set集合: set是一个无序且不重复的元素集合 建立一个集合: x = set([1, 'tom', 2, 3, 4]) print(type(x)) print(x) 以上实例运行后反回结果结 ...
- [LeetCode]题解(python):066-Plus One
题目来源: https://leetcode.com/problems/plus-one/ 题意分析: 给定一个数组,将数加一,返回新的数组.比如[9,9],返回[1,0,0]. 题目思路: 这道题目 ...
- Mac编程(QT有许多专门的资料)
Mac OS X 上在应用运行时,在Dock上的图标右键会有额外的菜单部分.参考iTunes运行时右键的菜单.使用Qt在Mac下的一个set_menu(QMenu *)函数实现,文档里有写 http: ...
- android串行化getSerializable、getSerializableExtra
android串行化getSerializable.getSerializableExtra 传参 总结 案例1 不用 Bundle 封装数据 提交activity lst.setOnItemClic ...
- Archive for required library: ‘WebContent/WEB-INF/lib/xxx.jar cannot&n
今天导入一个项目到eclipse,出现感叹号,而且报1. Archive for required library: ‘WebContent/WEB-INF/lib/xxxxx.jar cannot ...
- Maven 版 JPA 最佳实践
项目结构图 数据库环境 数据库:MySQL 版本:5.x 数据库名:jpa-demo 用户名密码:root/1234 代码清单 1:数据库脚本: /* Navicat MySQL Data Trans ...