zoukankan      html  css  js  c++  java
  • boost function对象

    本文根据boost的教程整理。

    主要介绍boost function对象的用法。

    boost function

    boost function是什么

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


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

    #include <boost/function.hpp>


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

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

    boost function 基本用法

    例如,有一个函数

    float int_div(int x, int y)
    {
        return ((float)x)/y;
    }
    


    我们可以这样使用

        boost::function<float (int x, int y)> f;
        f = int_div;
        std::cout<< f(5,3) << std::endl;
    


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

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

    struct int_add {
        float operator()(int x, int y) {
            return (float)(x + y);
        }
    };
    


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

        f = int_add();
        std::cout << "f add : "<< f(10,20) << std::endl;
    

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

        if(f)
            std::cout  << " f is ok!"<< std::endl;
    


    要清空f,可以使用

        f = 0;
        if(!f)
            std::cout << "f is cleard!" << std::endl;
    

    针对成员函数

    成员函数,也可以被绑定,如有类
    struct X {
        int foo(int x) {
            std::cout << "X " << this << " foo x="<<x << std::endl;
            return x + 100;
        };
    };
    

    可以这样使用
        boost::function<int (X*, int)> mf;
        mf = &X::foo;
    
        X x;
        mf(&x, 5);
    

    和bind同时使用

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

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


    function factory

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

    boost::factory<T*>()(arg1,arg2,arg3) 
    // same as new T(arg1,arg2,arg3)
    
    boost::value_factory<T>()(arg1,arg2,arg3)
    // same as T(arg1,arg2,arg3)

    使用function factory的原因

    我们考虑这样的场景:使用 抽象工厂模式,有一个接口,有若干个实现,通常的做法是这样的:
    //声明接口
    class Interface 
    {
    public:
       virtual void print(int a) = 0; //接口函数
    };
    //声明抽象工厂
    class Interface_Factory {
    public:
        virtual Interface * create() = 0;
    };

    然后,我们有若干个实现
    class ImplA : public Interface
    {
    public:
       virtual void print(int a) {
          std::cout << "== A ==  a=" << a << std::endl;
       }
    };
    //提供ImplA的类工厂
    class ImplA_Factory : public Interface_Factory
    {
    public:
        Interface * create() { return new ImplA(); }
        static ImplA_Factory _implAFactory;
    };
    ImplA_Factory ImplA_Factory::_implAFactory;
    
    //同理,ImplB的实现
    
    class ImplB : public Interface
    {
    public:
       virtual void print(int a) {
          std::cout << "== B ==  a=" << a << std::endl;
       }
    };
    //提供ImplB的类工厂
    class ImplB_Factory : public Interface_Factory
    {
    public:
        Interface * create() { return new ImplB(); }
        static ImplB_Factory _implBFactory;
    };
    ImplB_Factory ImplB_Factory::_implBFactory;
    
    如果你要使用它,就需要这些写
    std::map<std::string, Interface_Factory*> factories;
    
    int main()
    {
        factories["A"] = &ImplA_Factory::_implAFactory;
        factories["B"] = &ImplB_Factory::_implBFactory;
    .....
    }

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

    factory的解决之道

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

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

    OverloadedFunction

    考虑下面的代码
    const std::string& identity_s(const std::string& x) // Function (as pointer).
        { return x; }
    
    int identity_i_impl(int x) { return x; }
    int (&identity_i)(int) = identity_i_impl; // Function reference.
    
    double identity_d_impl(double x) { return x; }
    boost::function<double (double)> identity_d = identity_d_impl; // Functor.

    在调用他们的时候,必须使用各自的函数名:identity_i, indentity_s, indentity_d; 例如
    BOOST_TEST(identity_s("abc") == "abc");
    BOOST_TEST(identity_i(123) == 123);
    BOOST_TEST(identity_d(1.23) == 1.23);

    但是,使用OverlaodedFunction,就可以使用统一的名字identity来调用了:
    boost::overloaded_function<
          const std::string& (const std::string&)
        , int (int)
        , double (double)
    > identity(identity_s, identity_i, identity_d);
    
    // All calls via single `identity` function.
    BOOST_TEST(identity("abc") == "abc");
    BOOST_TEST(identity(123) == 123);
    BOOST_TEST(identity(1.23) == 1.23);



  • 相关阅读:
    第七周总结
    结对开发nabcd
    第六周总结
    地铁售票设计思想及部分代码
    第二周总结
    进度总结(地铁查询购票)
    第三周总结
    冲刺四
    冲刺三
    冲刺2
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3141026.html
Copyright © 2011-2022 走看看