boost库学习;

函数对象,成为‘高阶函数’,可以呗传入到其他函数或者从其他函数返回的一类函数。

Boost.Bind可替换来自c++标准中的std::bind1st()和std::bind2dn()函数

Boost.Function则提供了一个用于封装函数指针的类。

Boost.Lambda引入了一种创建匿名函数的方法。

===

bind提供了一种机制,将这些函数与不限数量的参数一起使用,可以得到指定签名的函数。

//=====

#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
void hello(){
    std::cout<<"hello world,I'm a thread from boost library"<<std::endl;
}

using namespace std;
void add(int i,int j){
    std::cout<<i+j<<std::endl;
}

int main() {
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    std::for_each(v.begin(),v.end(),boost::bind(add,10,_1));
    return 0;
}
//======

_1被称为占位符(placeholder),定义于boost.bind。除了_1,boost.bind还定义了_2和_3。通过这些占位符,bind可以变为一元、二元或者三元的函数。对于_1,boost::bind变为一个一元函数(即只要求一个参数的函数)。因为for_each(只要求一个一元函数作为其第三个参数。)

ps:简单来说,_1指代的是vector中的元素值,作为add函数的第一个参数,10默认作为第二个参数。bind的第一个参数值是add函数名字。

======

如果用于boost::bind()的函数带有至少一个引用参数时,Boost.Ref就重要了。因为bind会复制它的参数,引用必须特殊处理。

<boost/ref.hpp>

std::for_each(v.begin(), v.end(), boost::bind(add, 10, _1, boost::ref(std::cout)));

=======

boost.function()的功能,为了封装函数指针;

位于boost/function.hpp中,

用法是:boost::function<int (const char*)>f= std::strlen;

定一个函数指针,表示此函数接受的参数类型为const char*,返回的参数类型为int。定义完成后,匹配此签名的函数都可以复制给这个指针。

因为f是一个函数指针,被赋值的函数可以通过重载的operator()()操作符来调用。

另外当f未被赋值,而被调用的,会发生boost::bad_function_call异常。

//======

#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <boost/function.hpp>
#include <cstdlib>
#include <cstring>
struct world{
    void hello(std::ostream &os){
        os <<"helllo,world"<<std::endl;
    }
};

int main() {
    boost::function<int (const char*)> f = std::atoi;
    std::cout<<f("1292")<<endl;
    f = std::strlen;
    std::cout<<f("1609")<<std::endl;
    try {
        boost::function<int (const char*)> f2;
        f2("");
    }catch (boost::bad_function_call &ex){
        cout<<ex.what()<<endl;
    }

boost::function<void (world*,std::ostream &)> f3 = &world::hello;
    world w;
    f3(&w,boost::ref(std::cout));

return 0;
}

//======

=====

参考:http://zh.highscore.de/cpp/boost/functionobjects.html

// ======

boost 中的 function,bind ,shared_from_this 这三个方法常常会在一起使用,
并且经常用在回调函数中。这里所说的回调函数就是在一个主函数中,根据不同的情景来通过函数指针来调用不同情景下面的函数。

普通 c++98 通过函数指针来实现回调函数的示例
online_compiler

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std ;
  4. typedef void (* fun_t)(void) ;
  5. void fun0(void)
  6. {
  7. cout << "fun0 called " << endl ;
  8. }
  9. void fun1 ( void )
  10. {
  11. cout << "fun1 called " << endl ;
  12. }
  13. void fun2 ( void )
  14. {
  15. cout << "fun2 called " << endl ;
  16. }
  17. void (*cb_fun_list[3])(void) = {fun0 ,fun1 , fun2} ;
  18. void call_back ( int i )
  19. {
  20. fun_t funPtr ;
  21. if (i < 0 || i > 2 )
  22. {
  23. cout << " illegal function number " << endl ;
  24. return ;
  25. }
  26. funPtr = cb_fun_list[i] ;
  27. funPtr () ;
  28. }
  29. int main ()
  30. {
  31. call_back ( 2 ) ;
  32. call_back ( 0 ) ;
  33. call_back ( 1 ) ;
  34. return 0 ;
  35. }

boost 使用示例
online_compiler个人觉得下面的这个例子除了演示,bind 如何绑定带有参数的方法,并将其与以 function<...> 为参数的
方法对接之外,还有如何使用 shared_from_this () 没有实用价值,
因为我们在编程中很少会用到,类自己定义一个回调函数来回调自己类中的成员方法的。

回调方法通常应用与2或2个以上的类(结构体) 中的一个类中需要调用bind 方法而需要获得另一个类的对象实例传入
这种情况。比如说第三个例子中所讲的那样,不过第三个例子中没有实现 bind 方法中关于参数传递的处理。

关于 shared_from_this () , 这个方法通常是在类内部来使用,这个方法是用来返回一个 shared_ptr<T> 的指针,
也就是我们常使用到的“智能指针”中最有用的。同时如果要想让 shared_ptr<T> 对应的 T 是当前类的类型的话,
应该让当前的类继承 boost::enable_shared_from_this 这个类作为基类,同时在 enabled_shared_from_this 
后面类模板声明的时候,传入当前的类 , 即
class TestObj : public boost::enable_shared_from_this <TestObj>
{....} ;

还有一点值得注意的便是:
通过上述方法声明的类实例的创建,不能够使用简单的
TestObj testObj (...);
TestObj *testObjPtr = new TestObj () ; 
这种方法进行创建,因为 TestObj 继承了 enable_shared_from_this ,
所以它的初始化方法必须要在某种程度上按照 boost::enable_shared_from_this 的套路来,
所以,应该使用 shared_ptr 的方法来创建指向该对象的指针对象,然后通过指针对象来调用类实例中声明、定义一系列的方法。

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <boost/function.hpp>
  4. #include <boost/bind.hpp>
  5. #include <boost/enable_shared_from_this.hpp>
  6. using namespace std ;
  7. class obj : public boost::enable_shared_from_this<obj>
  8. {
  9. public :
  10. void runCallBack ( boost::function<int(int,int)> f , int x , int y )
  11. {
  12. cout << f( x, y ) << endl ;
  13. }
  14. int myadd ( int x , int y )
  15. {
  16. return x+y ;
  17. }
  18. void setCallBack ( int x , int y )
  19. {
  20. runCallBack( boost::bind( &obj::myadd , shared_from_this () , _1 , _2 ) ,x , y ) ;
  21. }
  22. private :
  23. boost::function<int( int ,int )> f;
  24. } ;
  25. int main ()
  26. {
  27. boost::shared_ptr<obj> pObj ( new obj ()) ;
  28. pObj->setCallBack(999, 1) ;
  29. return 0 ;
  30. }

boost 使用实例
虽然这仅仅是个简单的例子,但是我们可以把情况想象的更加复杂一些,
比如说 Manager 相当于是 RPC 框架中的服务器端的方法调用引擎,
当 Client 端给出需要远程调用的 function -- name , parameter-list 之后,将这些消息通过 socket 封装成消息
传递给服务器端的时候,服务器端的引擎 Manager 可以根据 function <>这个方法来锁定到应该调用哪一个方法来运行。
并把运行之后的结果同样包装成消息,并通过 socket 回复给请求的client。

不过上述的描述还需要大量的代码作为支撑,比如  client server 之间需要定义通信的协议以及 RPC 远程调用的方法的接口描述文件。
这个接口描述文件,可以将它们理解为 server 端为 client 端所提供的可调用方法的清单,同时 server 端可以通过类似于 register
的方法来将所有的方法函数以 function <> 的方式传入到一个 std::vector<function<> > 里面.
 
online_compiler

点击(此处)折叠或打开

  1. #include <boost/shared_ptr.hpp>
  2. #include <boost/enable_shared_from_this.hpp>
  3. #include <boost/function.hpp>
  4. #include <boost/bind.hpp>
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <iostream>
  8. #include <string>
  9. #include <vector>
  10. using namespace std ;
  11. using namespace boost ;
  12. class Manager
  13. {
  14. public :
  15. Manager ( )
  16. {}
  17. void registerCallBack ( boost::function<void ()> f )
  18. {
  19. cout << " in manager call input function " << endl ;
  20. fds.push_back(f) ;
  21. }
  22. void runCallBack ()
  23. {
  24. cout<< "running method defined in Node" << endl ;
  25. for ( int i = 0;i < fds.size() ; i++ )
  26. {
  27. boost::function<void()> f = fds[i] ;
  28. f() ;
  29. }
  30. fds.clear() ;
  31. }
  32. private :
  33. std::vector<boost::function<void()> > fds ;
  34. } ;
  35. class Node : public boost::enable_shared_from_this<Node>
  36. {
  37. public :
  38. Node () {}
  39. Node ( Manager *managerPtr )
  40. {
  41. pManager = managerPtr ;
  42. }
  43. void Aimer ( )
  44. {
  45. cout << " Aimer : hello i am Aimer " << endl ;
  46. }
  47. void Kokia ( )
  48. {
  49. cout << " Kokia : hello i am Kokia " << endl ;
  50. }
  51. void Kylin ( )
  52. {
  53. cout << " Kylin Zhang : ..... - _ - ......" << endl ;
  54. }
  55. void start ()
  56. {
  57. cout << " in method start " << endl ;
  58. pManager->registerCallBack(boost::bind(&Node::Aimer , shared_from_this() )) ;
  59. pManager->registerCallBack(boost::bind(&Node::Kokia , shared_from_this())) ;
  60. pManager->registerCallBack(boost::bind (&Node::Kylin , shared_from_this ())) ;
  61. }
  62. Manager *pManager ;
  63. } ;
  64. class Obj : public boost::enable_shared_from_this<Obj>
  65. {
  66. public :
  67. Obj ( Manager *pManager )
  68. {
  69. managerPtr = pManager ;
  70. }
  71. void start()
  72. {
  73. managerPtr->registerCallBack( boost::bind (&Obj::func1 , shared_from_this ()) ) ;
  74. managerPtr->registerCallBack( boost::bind ( &Obj::func2 , shared_from_this () )) ;
  75. }
  76. void func1()
  77. {
  78. cout << "func1 running "<< endl ;
  79. }
  80. void func2 ()
  81. {
  82. cout << "func 2 running " << endl ;
  83. }
  84. private :
  85. Manager* managerPtr ;
  86. } ;
  87. int main ()
  88. {
  89. Manager* pManager = new Manager() ;
  90. boost::shared_ptr<Node> nodePtr ( new Node ( pManager) ) ;
  91. boost::shared_ptr<Obj> objPtr ( new Obj (pManager) ) ;
  92. cout << " now i would like register methods defined in class Node into Manager function<void()> list " << endl ;
  93. nodePtr->start() ;
  94. cout << " now register methods in class Obj into Manager , by input parameter the pointer of class Manager instance " <<endl ;
  95. objPtr->start () ;
  96. cout <<" ------------------------ run method----------------------------" << endl ;
  97. pManager->runCallBack() ;
  98. return 0 ;
  99. }

end

[boost-3] 函数对象的更多相关文章

  1. boost库在工作(15)绑定器与函数对象之三

    前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行 ...

  2. 函数对象(仿函数 functor)

    简单地说,函数对象就是一个重载了()运算符的类实例,它可以像一个函数一样使用. #include <iostream> using namespace std; class Add { p ...

  3. javascript 利用匿名函数对象给你异步回调方法传参数

    先来创建一个匿名函数对象: /*** * 匿名函数 */ var callChangeBtn=new function(bugBtn){ this.chage=function(json){ bugB ...

  4. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  5. C++模板中的函数对象

    在C++模板类map中一个参数为Compare类型,该类型为一个比较函数,其完整定义如下: template< class Key, class T, class Compare = std:: ...

  6. C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象

    函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...

  7. EffectiveJava——用函数对象表示策略

    有些语言支持函数指针.代理.lambda表达式,或者支持类似的机制,允许程序把“调用特殊函数的能力”储存起来并传递这种能力.这种机制通常用于允许函数的调用者通过传入第二个函数,来指定自己的行为.比较器 ...

  8. python 学习笔记3(循环方式;list初始化;循环对象/生成器/表推导;函数对象;异常处理)

    ### Python的强大很大一部分原因在于,它提供有很多已经写好的,可以现成用的对象 16. 循环方式笔记: 1)range(0, 8, 2)   #(上限,下限,步长)  可以实现对元素或者下标的 ...

  9. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

随机推荐

  1. django-初始配置(纯手写)

    我们通过django-admin startproject zhuyu命令创建好项目后,在pycharm中打开 我们需要在在该项目中,配置一些相关操作. 1.template(存放模板的文件夹) 如果 ...

  2. 原生js的常见封装

    )); } ;;;;]){                 ];                 ] = ;;;,)     ,)     ,)     ,)         ,)         , ...

  3. Set linux mq_queue size for user

    设置调整mq_queue的size*num如果大于默认(POSIX message queues),则需要调整系统限制和用户限制,不然在mq_open是会报"Too many open fi ...

  4. SP1716 GSS3 - Can you answer these queries III(单点修改,区间最大子段和)

    题意翻译 nnn 个数, qqq 次操作 操作0 x y把 AxA_xAx​ 修改为 yyy 操作1 l r询问区间 [l,r][l, r][l,r] 的最大子段和 题目描述 You are give ...

  5. 微信小程序bindtap与catchtap的区别

    1.什么是事件 (1) 事件是视图层到逻辑层的通讯方式. (2) 事件可以将用户的行为反馈到逻辑层进行处理. (3) 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数. (4) ...

  6. Java中Lambda表达式的简单使用

    Lambda表达式是Java SE 8中一个重要的新特性.你可以把 Lambda表达式 理解为是一段可以传递的代码 (将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风格 ...

  7. redis 带入的挖矿病毒 qW3xT.2 wnTKYg 解决方法

    最近我的阿里云ecs 老是收到 云盾态势感知系统检测到异常 top -c 后发现一个 疑似病毒  /tmp/qW3xT.2 看到网友们的解决方案 试过之后效果不错,可以用的 知道wnTKYg是什么鬼之 ...

  8. Hadoop(22)-Hadoop数据压缩

    1.压缩概述 2.压缩策略和原则 3.MapReduce支持的压缩编码 64位系统下的单核i7,Snappy的压缩速率可以达到至少250MB/S,解压缩速率可以达到至少500MB/S 4.压缩方式选择 ...

  9. hadoop生态搭建(3节点)-05.mysql配置_单节点

    # ==================================================================node1 # ======================== ...

  10. 爬虫之requests模块基础

    一.request模块介绍 1. 什么是request模块 - python中原生的基于网络请求的模块,模拟浏览器发起请求. 2. 为什么使用request模块 - urllib需要手动处理url编码 ...