zoukankan      html  css  js  c++  java
  • 引领boost(六)(boost::bind)

    一 Boost::bind
       
       在STL中,我们经常需要使用bind1st,bind2st函数绑定器和fun_ptr,mem_fun等函数适配器,这些函数绑定器和函数适配器使用起来比较麻烦,需要根据是全局函数还是类的成员函数,是一个参数还是多个参数等做出不同的选择,而且有些情况使用STL提供的不能满足要求,所以如果可以我们最好使用boost提供的bind,它提供了统一的接口,提供了更多的支持,比如说它增加了shared_ptr,虚函数,类成员的绑定。

    二 源码剖析

     1) bind1st,bind2st函数绑定器,把二元函数对象变为一元函数对象。
     2) mem_fun,把成员函数变为函数对象。
     3) fun_ptr,把一般的全局函数变为函数对象。
     4) boost::bind(),包含了以上所有的功能。


    三 实例

     1)区别与mem_fun和fun_ptr

    #include <functional>
    #include 
    <iostream>
    #include 
    <string>
    #include 
    "boost/bind.hpp"
    class some_class 
    {
    public:      
        
    void print_string(const std::string& s) const
        
    {    
            std::cout 
    << s << '\n'
        }

        
    void print_classname()
        
    {
            std::cout 
    << "some_class" << std::endl;
        }

    }
    ;
    void print_string(const std::string s) 
    {  std::cout << s << '\n';
    }

    void print_functionname()
    {
        std::cout 
    << "Print_functionname" <<std::endl;
    }

    int main() 
    {  
        std::ptr_fun(
    &print_string)("hello1");
        
    //std::ptr_fun<void>(&print_functionname);
        some_class sc0;
        std::mem_fun_ref(
    &some_class::print_classname)(sc0);
        std::mem_fun_ref
    <void,some_class>(&some_class::print_classname)(sc0);
        
    //std::mem_fun1_ref<void,some_class,const std::stirng>(&some_class::print_string)(sc0,"hello2");

        (boost::bind(
    &print_string,_1))("Hello func!");  
        boost::bind(
    &print_functionname);
        some_class sc;  
        (boost::bind(
    &some_class::print_classname,_1)(sc));
        (boost::bind(
    &some_class::print_string,_1,_2))(sc,"Hello member!");
    }

     2)区别与bind1st和bind2st

    #include <functional>
    #include 
    <iostream>
    #include 
    <string>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    "boost/bind.hpp"
    void main()
    {
        std::vector
    <int> ints;
        ints.push_back(
    7);
        ints.push_back(
    4);
        ints.push_back(
    12);
        ints.push_back(
    10);
        
    int count=std::count_if(ints.begin(),  
            ints.end(), 
            boost::bind(std::logical_and
    <bool>(),boost::bind(std::greater<int>(),_1,5),boost::bind(std::less_equal<int>(),_1,10))
            );
        std::cout 
    << count << '\n';
        std::vector
    <int>::iterator int_it=std::find_if(ints.begin(),  
            ints.end(),  
            boost::bind(std::logical_and
    <bool>(),boost::bind(std::greater<int>(),_1,5),boost::bind(std::less_equal<int>(),_1,10))
            );
        
    if (int_it!=ints.end()) 
        
    {  std::cout << *int_it << '\n';}

    }

     3)区别传ref和传instance

    // bind instance or reference
    #include <functional>
    #include 
    <iostream>
    #include 
    <string>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    "boost/bind.hpp"
    class tracer 
    {
    public
        tracer() 
    {    std::cout << "tracer::tracer()\n";  } 
        tracer(
    const tracer& other) {    std::cout << "tracer::tracer(const tracer& other)\n";  } 
        tracer
    & operator=(const tracer& other)
        
    {    std::cout <<      "tracer& tracer::operator=(const tracer& other)\n";    return *this;  } 
        
    ~tracer() {    std::cout << "tracer::~tracer()\n"
        }
     
        
    void print(const std::string& s) const
        
    {    std::cout << s << '\n';  }
    }
    ;

    void main()
    {
        tracer t;
        boost::bind(
    &tracer::print,t,_1)(std::string("I'm called on a copy of t\n"));
        tracer t1;
        boost::bind(
    &tracer::print,boost::ref(t1),_1)(  std::string("I'm called directly on t\n"));

    }

     4)绑定虚函数

    //bind vitual class function
    #include <functional>
    #include 
    <iostream>
    #include 
    <string>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    "boost/bind.hpp"
    class base {
    public:
        
    virtual void print() const 
        
    {    std::cout << "I am base.\n";  
        }
      
        
    virtual ~base() {}
    }
    ;
    class derived : public base 
    {
    public
        
    void print()const 
        
    {    std::cout << "I am derived.\n";  }
    }
    ;

    void main()
    {
        derived d;
        
    base b;
        boost::bind(
    &base::print,_1)(b);
        boost::bind(
    &base::print,_1)(d);
    }

     5)绑定成员变量

    // bind class's member
    #include <functional>
    #include 
    <iostream>
    #include 
    <string>
    #include 
    <vector>
    #include 
    <algorithm>
    #include 
    "boost/bind.hpp"
    class personal_info 

        std::
    string name_;  
        std::
    string surname_;
        unsigned 
    int age_;
    public
        personal_info(
    const std::string& n,const std::string& s,unsigned int age):name_(n),surname_(s),age_(age) {} 
        std::
    string name() const {return name_;} 
        std::
    string surname() const {return surname_;} 
        unsigned 
    int age() const {return age_;}
    }
    ;

    void main()
    {
     std::vector
    <personal_info> vec;
     vec.push_back(personal_info(
    "Little","John",30));
     vec.push_back(personal_info(
    "Friar""Tuck",50));
     vec.push_back(personal_info(
    "Robin""Hood",40));
     std::sort(vec.begin(),
         vec.end(),
         boost::bind(std::less
    <unsigned int>(),boost::bind(&personal_info::age,_1),boost::bind(&personal_info::age,_2))
         );
     std::sort(vec.begin(),
         vec.end(),
         boost::bind(std::less
    <std::string>(),boost::bind(&personal_info::surname,_1),boost::bind(&personal_info::surname,_2))
         );
    }

    四 注意

     1) 现在的类库最多可以支持9个参数。
     2)在绑定一个成员函数时,bind 表达式的第一个参数必须是成员函数所在类的实例!理解这个规则的最容易的方法是,这个显式的参数将取替隐式的 this ,被传递给所有的非静态成员函数。细心的读者将会留意到,实际上这意味着对于成员函数的绑定器来说,只能支持八个参数,因为第一个要用于传递实际的对象。

    3)当我们传递某种类型的实例给一个 bind 表达式时,它将被复制,除非我们显式地告诉 bind 不要复制它。要避免复制,我们必须告诉bind 我们想传递引用而不是它所假定的传值。我们要用 boost::ref 和 boost::cref (分别用于引用和 const 引用)来做到这一点,它们也是Boost.Bind 库的一部分。还有一种避免复制的方法;就是通过指针来传递参数而不是通过值来传递。

     4) 通过 Boost.Bind, 你可以象使用非虚拟函数一样使用虚拟函数,即把它绑定到最先声明该成员函数为虚拟的基类的那个虚拟函数上。这个绑定器就可以用于所有的派生类。如果你绑定到其它派生类,你就限制了可以使用这个绑定器的类。

    5)bind还可以绑定成员变量。

  • 相关阅读:
    (转载)VS2010/MFC编程入门之十九(对话框:颜色对话框)
    (转载)VS2010/MFC编程入门之十八(对话框:字体对话框)
    (转载)VS2010/MFC编程入门之十七(对话框:文件对话框)
    (转载)VS2010/MFC编程入门之十六(对话框:消息对话框)
    VS2010/MFC编程入门之十四(对话框:向导对话框的创建及显示)
    (转载)VS2010/MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)
    (转载)VS2010/MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)
    Android笔记之AsyncTask
    Android笔记之线程使用
    Android笔记之活动指示器使用
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1934733.html
Copyright © 2011-2022 走看看