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. java使用JSCH连接FTP(Linux服务器)上传文件到Linux服务器

    首先需要用到jsch-0.1.54.jar 包: 链接: https://pan.baidu.com/s/1kZR6MqwpCYht9Pp_D6NKQw 密码: gywx 直接上代码: package ...

  2. vue组件原生事件以及路由

    1.组件 组件就是可以扩展HTML元素,封装可重用的HTML代码,可以将组件看作自定义的HTML元素 1.1组件注册 全局注册: 组件注册时,需要给他一个名字,如下: Vue.component('m ...

  3. 简易Dubbo的搭建过程

    dubbo是一个高性能的,基于java的,开源RPC框架,主要功能是让构建分布式计算更加容易. (分布式:多台计算机实现不同功能,形成一个整体对外服务) (集群式:多台计算机实现相同功能,分担计算压力 ...

  4. 每天一个Linux命令(6):rmdir命令

    rmdir命令用来删除空目录 注意:子目录被删除之前应该是空目录.就是说,该目录中的所有文件必须用rm命令全部,另外,当前工作目录必须在被删除目录之上,不能是被删除目录本身,也不能是被删除目录的子目录 ...

  5. iOS之查看代码运行的时间

    有时候我们想要准确的知道某段代码.某个循环执行的时间,然后分析效率等问题,这个时候就需要执行时间是多少.正好看到网上已经有人做了这个工作,我就直接摘下来了.正好也用了宏的方式计算时间,我们只要在需要计 ...

  6. ABAP术语-Business Framework

    Business Framework 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/28/1017922.html Integrated, ...

  7. Percona-Tookit工具包之pt-query-digest

      Preface       Performance issues are what DBA most concerned thing.There're always a lot of SQL qu ...

  8. JavaScript文本框焦点事件

    效果图如下: <!-- 当文本框获得焦点时候,如果文本框内容是 请输入搜索关键字 清空文本框,输入内容变黑色 --> <!-- 当文本框失去焦点时候,如果文本框无内容,则添加灰色的 ...

  9. 吐血分享:QQ群霸屏技术教程2017(活跃篇)

    热门词的群排名,在前期优化准备充分的情况下,活跃度不失为必杀技. 在<吐血分享:QQ群霸屏技术(初级篇)>中,我们提及到热门词的群排名,有了前面的基础,我们就可以进入深度优化,实现绝对的霸 ...

  10. Hive(2)-Hive的安装,使用Mysql替换derby,以及一丢丢基本的HQL

    一. Hive下载 1. Hive官网地址 http://hive.apache.org/ 2. 文档查看地址 https://cwiki.apache.org/confluence/display/ ...