前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行了,因为它最多只支持两个参数,那还有什么办法呢?这时就需要使用boost库里强大的绑定器bind了。它不仅适用的情况比STL库里的多,还更加方便,更加人性化。下面就来看看怎么样绑定三个参数的类成员函数的例子,如下:

  1. //调用类的成员函数,但参数两个以上。
  2. //软件开发人员: 蔡军生  2013-02-10
  3. //QQ: 9073204
  4. class CObjBind
  5. {
  6. public:
  7. void Test(void)
  8. {
  9. //
  10. std::vector< int > vRect;
  11. vRect.push_back(1);
  12. vRect.push_back(2);
  13. vRect.push_back(3);
  14. vRect.push_back(10);
  15. //使用绑定器来调用类成员函数
  16. std::cout << "First:"<<std::endl;
  17. std::for_each(vRect.begin(), vRect.end(),
  18. boost::bind(&CObjBind::Fun, this, _1, 1, 2));
  19. std::cout << "Second:"<<std::endl;;
  20. std::for_each(vRect.begin(), vRect.end(),
  21. boost::bind(&CObjBind::Fun, this, 1, _1, 2));
  22. }
  23. private:
  24. void Fun(int x, int y, int z)
  25. {
  26. std::cout << "CObjBind::Fun:" << x << "," << y << "," << z << std::endl;
  27. }
  28. };

在这个例子里看到使用绑定器的代码行,如下:

boost::bind(&CObjBind::Fun, this, _1, 1, 2)

绑定器bind的第一个参数直接使用类成员函数指针就行了,不像前面要添加mem_fun函数来转换;第二个参数是继续输入this指针;第三个参数是_1,前面带下划线的1是比较奇怪了,其实这个是bind器的占位符,用来指定生成的函数对象参数传给绑定的函数参数顺序;最后两个参数都传送给函数的参数。这样函数void Fun(int x, int y, int z)的三个参数就传送过了,大体就是这样调用Fun(_1,1,2)。因而输出的结果如下:

CObjBind::Fun:1,1,2

CObjBind::Fun:2,1,2

CObjBind::Fun:3,1,2

CObjBind::Fun:10,1,2

从输出的结果中可以看到,占位符在那里就是算法for_each传入参数的地方。相当如下的调用:

Fun(x,1,2)(x);

接着来看占位符放到第二个位置,如下这样:

std::for_each(vRect.begin(), vRect.end(),

boost::bind(&CObjBind::Fun,this, 1, _1, 2));

这里占位_1放在第二个参数位置,输出的结果如下:

CObjBind::Fun:1,1,2

CObjBind::Fun:1,2,2

CObjBind::Fun:1,3,2

CObjBind::Fun:1,10,2

跟前面的比较,算法for_each传入的值在第二个参数传入。

boost库里的绑定器bind与STL里定义的两个相比,参数比较多,可以多达9个,也许你会问,如果多于9个怎么样办呢?多于9个的情况是比较少的,就算有了,在这种情况之下,也需要定义一个数据结构来保存,传递一个指针进来比较合算,因为这样参数少,方便维护,同样传送的效率提高了。第二个优点是绑定成员函数简单,不需要调用mem_fun函数,第三个优点是提供占位符,可以随便指定到那个参数传入。9个参数的占位符的名称是_1,_2,_3,一直接到_9。

boost库里的绑定器是兼容比较好,还可以支持STL里的二元运算函数的绑定,如下:

bool bResult =bind(std::less<int>(), 5, 9)();

std::cout << bResult<< std::endl;

下面再来看一个复杂一点的例子,比如实现对值x进行这样的判断:

if (x > 10 && x <= 20)

{

}

使用绑定器就可以写成下面这样:

//实现 if ( x > 10 && x <= 20)

boost::bind(  std::logical_and<bool>(),

boost::bind(std::greater<int>(),_1, 10),

boost::bind(std::less_equal<int>(),_1, 20))(15);

通过这样的组合,就可以实现很复杂的表达式运算,这样就可以给算法提供更加复杂的条件,达到我们需要达到的目的。

如下面的例子,可以合适地删除指定条件的元素:

vRect.erase(std::remove_if(vRect.begin(), vRect.end(),

boost::bind(&CObjBind::IsLess,this, _1)), vRect.end());

在这个例子里,先调用算法remove_if来删除数组中小于指定条件的元素,并返回无效元素的起始位置,然后调用vRect.erase删除后面无效的元素,最终在数组里就剩下有效的元素了。

总之,绑定器已经成为boost库里不可缺少的一部份了,比如算法、线程、网络等库中,都需要使用绑定器进行适配,以便达到高效、简洁、方便等目的。

boost库在工作(15)绑定器与函数对象之三的更多相关文章

  1. boost库在工作(33)网络服务端之三

    在这个例子里,表示服务器与一个客户端的沟通渠道,就是一个连接,封装为类CConnect.它是当服务器接收到一个客户端连接请求之后创建的,主要用来就是管理这个连接的生命周期,以及数据的接收和发送.从生命 ...

  2. boost库在工作(37)网络UDP服务端之七

    前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...

  3. boost库在工作(39)网络UDP异步服务端之九

    前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的.如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以 ...

  4. boost库在工作(40)串行通讯

    现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...

  5. boost库在工作(32)网络服务端之二

    在这个例子里,服务器对象主要使用boost::asio::io_service对象,这个对象主要用来构造异步接收数据使用,接着定义boost::asio::ip::tcp::acceptor对象,这个 ...

  6. boost库在工作(36)网络服务端之六

    在上面介绍了管理所有连接的类,这个类主要就是添加新的连接,或者删除不需要的连接.但是管理的类CAllConnect是没有办法知道什么时候添加,什么时候删除的,它需要从接收到连接类里获取得到新的连接,从 ...

  7. 【Boost】boost库asio详解2——io_service::run函数无任务时退出的问题

    io_service::work类可以使io_service::run函数在没有任务的时候仍然不返回,直至work对象被销毁. void test_asio_nowork() { boost::asi ...

  8. C++11绑定器bind及function机制

    前言 之前在学muduo网络库时,看到陈硕以基于对象编程的方式,大量使用boost库中的bind和function机制,如今,这些概念都已引入至C++11,包含在头文件<functional&g ...

  9. Linux/ubuntu下的boost库安装

    我一直都没有写博客的习惯,最近正好在研究linux下的开发(目前也只是粗粗的研究),且用到了boost库,就乘此机会写点什么,最起码记录一下我在安装boost的一些步骤,主要给和我一样的linux开发 ...

随机推荐

  1. 关于javascript输出中文乱码的问题

    今天找到一个引导效果.原来是用英文进行引导.但是我改了里面的英文为汉字就出现乱码的情况.英文提示是在js页面里面完成的.所以最后的解决办法 就是把js文件用记事本打开,然后把文件另存为utf-8的格式 ...

  2. Dynamic Web Module 3.0 requires Java 1.6 or newer报错

    在项目的pom.xml的<build></build>标签中加入: <plugins> <plugin> <groupId>org.apac ...

  3. php基础知识【函数】(6)mysql数据库

    一.连接和关闭 1.mysql_connect('example.com:3307', 'root', '123456') --打开一个到 MySQL 服务器的非永久连接 2.mysql_pconne ...

  4. document模板

    http://bce.baidu.com/doc/CDS/GettingStarted.html

  5. IPython学习笔记

    IPython 前言 Life is short, you need Python 最近开始学习数据挖掘,需要使用到Python,其实大学时代就有接触过Python,但是却始终没有系统的进行学习过. ...

  6. webkit report

    %for main_o in objects: <% print main_o.sale_announcement_ids %> %for o in announcement_pool.b ...

  7. MySQL 执行计划explain详解

    MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...

  8. Objective-C基础 便利构造器 单例模式1-17

    Objective-C基础 便利构造器 单例模式1-17 便利构造器 单例模式 1.在声明时指定setter或getter方法,则用点运算符方法调用时默认调用的就是自己指定的方法2.单例:唯一性,如: ...

  9. 【Winform 控件浅谈 】 之 WebBrowser

    前言 鄙人才疏学浅,如果说错了,还请各位不吝赐教 1.什么是 WebBrowser 下面是已有的轮子,我想说它们是专业的 http://baike.baidu.com/view/2981935.htm ...

  10. Oracle问题解决(远程登录失败)

    远程机: 安装 Oracle 的计算机: 本地机: 访问远程机 Oracle 的计算机. 一.问题描述 远程机安装 Oracle 成功. 本地机配置 InstantClient 后, PLSql De ...