boost::function 简单实现理念
来源:互联网 发布:Mac mplayerx全屏白屏 编辑:程序博客网 时间:2024/05/01 11:04
前面在做http server的时候,需要做一个回调的接口,要求能够绑定类的函数以及普通的函数到这个回调里,对于这种应用要求,选择boost的bind和function是最合适不过了,但现在情况有些不同,我不准备在现在做的这个东西里加入boost, 本着以造轮子为乐的精神,现在只能捋起袖子自己来搞一个。
大概原型
使用的时候一直没有太留意它们的实现,现在要做起来,发现也不是想像中那么轻而易举。这个东西做到最后要实现的效果就是设计一个泛型的function holder,这个holder既能包装类的函数,又要能包装一般的函数,换言之就是能像下面一样来使用。
#include <iostream>using namespace std;class cs{ public: int proc(double d) { cout << "mem func proc:" << d << endl; return (int)d;}};int Proc(double d){ cout << "normal proc:" << d << endl; return (int)d;}int main(){ function fun = &Proc; fun(2.3); cs c; fun = bind(&cs::proc, &c); fun(3.3); return 0;}
简单实现
一开始你可能会想,piece of cake! 直接封装一个function就行了。
template<class ret_type, class arg_type>class function1: public copyable{ public: typedef ret_type (* NORM_PROC) (arg_type); function1(NORM_PROC proc = 0): fun_(proc){} ret_type operator() (arg_type arg) { fun_->operator()(arg); } private: NORM_PROC fun_;};
好,这个类可以封装一般的函数了,那类的函数呢?one more!
template<class CS, class ret_type, class arg_type>class function2: public copyable{ public: typedef ret_type (CS::* MEM_PROC)(arg_type); function2(CS* obj, MEM_PROC proc): obj_(obj), proc_(proc) {} ret_type operator() (arg_type arg) { return (obj_->*proc_)(arg); } private: CS* obj_; MEM_PROC proc_;};
很快我们就发现有问题了,function1和function2是两不同的模板类,bind()的时候没法处理:bind()返回的应该要是一个统一的类型。
怎么办呢?我们可能想到要抽取出一个基类来,思路是对的!但还有些细节要处理。
比如:bind()返回的是什么类型呢?function1,function2的基类吗?这好像做不到,不能直接返回object。
template<class ret_type, class arg_type>class function_base:public copyable{ public: virtual ~function_base(){} ret_type operator() (arg_type arg) = 0;};template<class CS, class ret_type, class arg_type>class function2: public function_base{ public: typedef ret_type (CS::* MEM_PROC)(arg_type); function2(CS* obj, MEM_PROC proc): obj_(obj), proc_(proc) {} ret_type operator() (arg_type arg) { return (obj_->*proc_)(arg); } private: CS* obj_; MEM_PROC proc_;};template<class CS, class ret_type, class arg_type>function_base<ret_type, arg_type> bind(ret_type (CS::* proc)(arg_type), CS* pc){ function2<CS, ret_type, arg_type> func_holder(pc, proc); return func_holder; //object slicing}
那直接返回指针不就完了!
返回指针可行,但不好用,而且容易内存泄漏。解决的办法是对返回的指针再包一层,嗯,RAII.
等等,好像如果再包一层,就已经能直接隔开底下的function holder与具体的调用了啊!Perfect!
template<class ret_type, class arg_type>class function_base:public copyable{ public: virtual ~function_base() {} ret_type operator() (arg_type arg) = 0;};template<class ret_type, class arg_type>class function1:public function_base{ public: typedef ret_type (* NORM_PROC) (arg_type); function1(NORM_PROC proc = 0): fun_(proc){} ret_type operator() (arg_type arg) { fun_->operator()(arg); } private: NORM_PROC fun_; };template<class CS, class ret_type, class arg_type>class function2: public function_base{ public: typedef ret_type (CS::* MEM_PROC)(arg_type); function2(CS* obj, MEM_PROC proc): obj_(obj), proc_(proc) {} ret_type operator() (arg_type arg) { return (obj_->*proc_)(arg); } private: CS* obj_; MEM_PROC proc_;};template<class ret_type, class arg_type>class functioin:public copyable{ public: function(function_base<ret_type, arg_type>* pf): _obj(pf) {} ret_type operator()(arg_typearg){fun_->operator()(arg);} private: function_base<ret_type, arg_type>* obj_;};template<class CS, class ret_type, class arg_type>function<ret_type, arg_type> bind(ret_type (CS::* proc)(arg_type), CS* pc){ return new function2<CS, ret_type, arg_type>(pc, proc);}
经过这样一包装,function类好像已经能够用来bind类的函数了, 也没那么难嘛!
但是,代码很差劲:
1) 没有处理内存释放。
2) 没有处理copy costructor , assignment operator()。
3) 普通函数还是不能直接赋值给function类。
再改一下function类:
template<class ret_type, class arg_type>class function{ public: typedef ret_type (* NORM_PROC) (arg_type); function(function_base<ret_type, arg_type>* fun): fun_(fun), ref_(new int(1)) {} function(NORM_PROC proc = 0): fun_(new function1<ret_type, arg_type>(proc)), ref_(new int(1)) {} ret_type operator() (arg_type arg) { fun_->operator()(arg); } ~function() { Release(); } void Release() { *ref_ -= 1; if (*ref_ == 0) { delete ref_; delete fun_; } } function(const function& fun) { fun_ = fun.fun_; ref_ = fun.ref_; *ref_ += 1; } void operator=(const function& fun) { Release(); fun_ = fun.fun_; ref_ = fun.ref_; *ref_ += 1; } private: int* ref_; function_base<ret_type, arg_type>* fun_;};
这样一来,终于能够正常使用了。
- boost::function 简单实现理念
- boost bind及function的简单实现
- boost function 实现
- boost::function boost::bind 简单示例
- boost::function的简单用法
- boost之function的简单使用
- boost之function的简单使用
- boost多线程简单实现
- boost::lexical_cast简单实现
- 在VC6中实现Boost::Bind/Function
- 使用boost::bind和boost::function实现工厂模式
- function 源码分析1--boost function缩水版本实现
- boost::function
- Boost.Function
- boost::function
- boost:function
- boost::function
- boost::function
- php实现一个分页类
- 欢聚时代校园招聘java开发一面经历
- Java基本概念总结
- 360公司2015年秋季校园招聘笔试考卷(技术类 D)部分试题程序验证和解析1
- matlab中一些常用的函数
- boost::function 简单实现理念
- 我们到底在多大程度上依赖权威?
- 解决异常:Adb connection Error:远程主机强迫关闭了一个现有的连接。
- 判断回文
- 二维数组指针
- java 线程 生产者-消费者与队列,任务间使用管道进行输入、输出 讲解示例 --thinking java4
- thingking in Java 容器深入研究
- 国外论文搜索
- 开发人员体验测试工作