boost::function的用法(二)

122 篇文章 1 订阅
21 篇文章 0 订阅

boost function是一组类和模板组合,用于包装各种函数。从功能上,它类似于函数指针,但是比函数指针的功能更强大。

使用boost function,必须包含头文件

[cpp]  view plain  copy
  1. #include <boost/function.hpp>  

除了头文件外,不需要额外的库。

注意,boost function有两种形式:一种为推荐形式;另外一种为可移植形式。推荐形式的语法更加简洁;可移植形式的可移植性好,但是语法罗嗦。由于目前的gcc/vc的版本都已经能够使用推荐形式了,因此,可移植形式就不在描述。有兴趣的可以参阅boost相关文档。

boost function 基本用法

例如,有一个函数

[cpp]  view plain  copy
  1. float int_div(int x, int y)  
  2. {  
  3.     return ((float)x)/y;  
  4. }  

我们可以这样使用

[cpp]  view plain  copy
  1. boost::function<float (int x, int y)> f;  
  2. f = int_div;  
  3. std::cout<< f(5,3) << std::endl;  

可以看到,它的用法和函数指针很相似的。

当然,boost::function不止这些,请看下面的函数对象:

[cpp]  view plain  copy
  1. struct int_add {  
  2.     float operator()(int x, int y) {  
  3.         return (float)(x + y);  
  4.     }  
  5. };  

上面的 boost::function<float (int x, int y)> f 声明的f对象,仍旧可以保存int_add:

[cpp]  view plain  copy
  1. f = int_add();  
  2. std::cout << "f add : "<< f(10,20) << std::endl;  

另外,boost::function还可以用来判断函数是否为空

[cpp]  view plain  copy
  1. if(f)  
  2.     std::cout  << " f is ok!"<< std::endl;  

要清空f,可以使用

[cpp]  view plain  copy
  1. f = 0;  
  2. if(!f)  
  3.     std::cout << "f is cleard!" << std::endl;  

针对成员函数

成员函数,也可以被绑定,如有类
[cpp]  view plain  copy
  1. struct X {  
  2.     int foo(int x) {  
  3.         std::cout << "X " << this << " foo x="<<x << std::endl;  
  4.         return x + 100;  
  5.     };  
  6. };  

可以这样使用
[cpp]  view plain  copy
  1. boost::function<int (X*, int)> mf;  
  2. mf = &X::foo;  
  3.   
  4. X x;  
  5. mf(&x, 5);  

和bind同时使用

在需要包装参数的场合,我们可以配合boost::bind一起使用。
首先,加入boost::bind的头文件
[cpp]  view plain  copy
  1. #include <boost/bind.hpp>  
这样使用
[cpp]  view plain  copy
  1. boost::function<int (int)> mbf;  
  2. mbf = bind(&X::foo, &x, _1);  
  3. mbf(10);  

bind将x的指针保存在function对象中。


function factory

function factory是一个封装类工厂的模板。它有两种,一种是value_factory,一种是factory。

[cpp]  view plain  copy
  1. boost::factory<T*>()(arg1,arg2,arg3)   
  2. // same as new T(arg1,arg2,arg3)  
  3.   
  4. boost::value_factory<T>()(arg1,arg2,arg3)  
  5. // same as T(arg1,arg2,arg3)  

使用function factory的原因

我们考虑这样的场景:使用 抽象工厂模式,有一个接口,有若干个实现,通常的做法是这样的:
[cpp]  view plain  copy
  1. //声明接口  
  2. class Interface   
  3. {  
  4. public:  
  5.    virtual void print(int a) = 0; //接口函数  
  6. };  
  7. //声明抽象工厂  
  8. class Interface_Factory {  
  9. public:  
  10.     virtual Interface * create() = 0;  
  11. };  

然后,我们有若干个实现
[cpp]  view plain  copy
  1. class ImplA : public Interface  
  2. {  
  3. public:  
  4.    virtual void print(int a) {  
  5.       std::cout << "== A ==  a=" << a << std::endl;  
  6.    }  
  7. };  
  8. //提供ImplA的类工厂  
  9. class ImplA_Factory : public Interface_Factory  
  10. {  
  11. public:  
  12.     Interface * create() { return new ImplA(); }  
  13.     static ImplA_Factory _implAFactory;  
  14. };  
  15. ImplA_Factory ImplA_Factory::_implAFactory;  
  16.   
  17. //同理,ImplB的实现  
  18.   
  19. class ImplB : public Interface  
  20. {  
  21. public:  
  22.    virtual void print(int a) {  
  23.       std::cout << "== B ==  a=" << a << std::endl;  
  24.    }  
  25. };  
  26. //提供ImplB的类工厂  
  27. class ImplB_Factory : public Interface_Factory  
  28. {  
  29. public:  
  30.     Interface * create() { return new ImplB(); }  
  31.     static ImplB_Factory _implBFactory;  
  32. };  
  33. ImplB_Factory ImplB_Factory::_implBFactory;  
如果你要使用它,就需要这些写
[cpp]  view plain  copy
  1. std::map<std::string, Interface_Factory*> factories;  
  2.   
  3. int main()  
  4. {  
  5.     factories["A"] = &ImplA_Factory::_implAFactory;  
  6.     factories["B"] = &ImplB_Factory::_implBFactory;  
  7. .....  
  8. }  

如果仔细观察下,就会发现,实际上,ImplA_Factory和ImplB_Factory的内容几乎都一样。但是却写了不少重复性的代码。factory就是解决该问题的。

factory的解决之道

使用boost::factory,是完全不需要定义Interface_Factory接口和对应的实现的,我们定义一个boost::function对象,替代Interface_Factory
[cpp]  view plain  copy
  1. typedef boost::function< I *() > I_factory; //替代Interface_Factory的定义  
用boost::factory替代ImplA_Factory和ImplB_Factory:
[cpp]  view plain  copy
  1. std::map<std::string, I_factory> factories;  
  2. ....  
  3.   
  4.     factories["A"] = boost::factory<ImplA*> ();  //等价于 &ImplA_Factory::_ImplAFactory;  
  5.     factories["B"] = boost::factory<ImplB*> (); //等价于 &ImplB_Factory::_ImplBFactory;  

在使用的时候,与普通方法丝毫不差,如
[cpp]  view plain  copy
  1. void run_interface(const char* name)  
  2. {  
  3.     I_factory factory = factories[name];  
  4.     if(!factory)  
  5.     {     
  6.         std::cout<<"factory " << name << " is not exist" << std::endl;  
  7.         return;  
  8.     }     
  9.     I *i = factory();  
  10.     i->print(100);  
  11.     delete i;  
  12. }  
通过判断factory的函数是否为空,就可以知道对应的类实现是否存在。我们可以这样简单的使用
[cpp]  view plain  copy
  1. run_interface("A");  
  2. run_interface("B");  
  3. run_interface("C");  
由于"C"对象不存在,因此,将打印 "factory C is not exist"的信息。

OverloadedFunction

考虑下面的代码
[cpp]  view plain  copy
  1. const std::string& identity_s(const std::string& x) // Function (as pointer).  
  2.     { return x; }  
  3.   
  4. int identity_i_impl(int x) { return x; }  
  5. int (&identity_i)(int) = identity_i_impl; // Function reference.  
  6.   
  7. double identity_d_impl(double x) { return x; }  
  8. boost::function<double (double)> identity_d = identity_d_impl; // Functor.  

在调用他们的时候,必须使用各自的函数名:identity_i, indentity_s, indentity_d; 例如
[cpp]  view plain  copy
  1. BOOST_TEST(identity_s("abc") == "abc");  
  2. BOOST_TEST(identity_i(123) == 123);  
  3. BOOST_TEST(identity_d(1.23) == 1.23);  

但是,使用OverlaodedFunction,就可以使用统一的名字identity来调用了:
[cpp]  view plain  copy
  1. boost::overloaded_function<  
  2.       const std::string& (const std::string&)  
  3.     , int (int)  
  4.     , double (double)  
  5. > identity(identity_s, identity_i, identity_d);  
  6.   
  7. // All calls via single `identity` function.  
  8. BOOST_TEST(identity("abc") == "abc");  
  9. BOOST_TEST(identity(123) == 123);  
  10. BOOST_TEST(identity(1.23) == 1.23);  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值