您的位置:首页 > 其它

boost::function的用法(二)

2017-07-04 19:37 295 查看


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

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

[cpp] view
plain copy

#include <boost/function.hpp>  

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

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


boost function 基本用法

例如,有一个函数

[cpp] view
plain copy

float int_div(int x, int y)  

{  

    return ((float)x)/y;  

}  

我们可以这样使用

[cpp] view
plain copy

boost::function<float (int x, int y)> f;  

f = int_div;  

std::cout<< f(5,3) << std::endl;  

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

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

[cpp] view
plain copy

struct int_add {  

    float operator()(int x, int y) {  

        return (float)(x + y);  

    }  

};  

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

[cpp] view
plain copy

f = int_add();  

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

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

[cpp] view
plain copy

if(f)  

    std::cout  << " f is ok!"<< std::endl;  

要清空f,可以使用

[cpp] view
plain copy

f = 0;  

if(!f)  

    std::cout << "f is cleard!" << std::endl;  


针对成员函数

成员函数,也可以被绑定,如有类

[cpp] view
plain copy

struct X {  

    int foo(int x) {  

        std::cout << "X " << this << " foo x="<<x << std::endl;  

        return x + 100;  

    };  

};  

可以这样使用

[cpp] view
plain copy

boost::function<int (X*, int)> mf;  

mf = &X::foo;  

  

X x;  

mf(&x, 5);  


和bind同时使用

在需要包装参数的场合,我们可以配合boost::bind一起使用。

首先,加入boost::bind的头文件

[cpp] view
plain copy

#include <boost/bind.hpp>  

这样使用

[cpp] view
plain copy

boost::function<int (int)> mbf;  

mbf = bind(&X::foo, &x, _1);  

mbf(10);  

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


function factory

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

[cpp] view
plain copy

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的原因

我们考虑这样的场景:使用抽象工厂模式,有一个接口,有若干个实现,通常的做法是这样的:

[cpp] view
plain copy

//声明接口  

class Interface   

{  

public:  

   virtual void print(int a) = 0; //接口函数  

};  

//声明抽象工厂  

class Interface_Factory {  

public:  

    virtual Interface * create() = 0;  

};  

然后,我们有若干个实现

[cpp] view
plain copy

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;  

如果你要使用它,就需要这些写

[cpp] view
plain copy

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

[cpp] view
plain copy

typedef boost::function< I *() > I_factory; //替代Interface_Factory的定义  

用boost::factory替代ImplA_Factory和ImplB_Factory:

[cpp] view
plain copy

std::map<std::string, I_factory> factories;  

....  

  

    factories["A"] = boost::factory<ImplA*> ();  //等价于 &ImplA_Factory::_ImplAFactory;  

    factories["B"] = boost::factory<ImplB*> (); //等价于 &ImplB_Factory::_ImplBFactory;  

在使用的时候,与普通方法丝毫不差,如

[cpp] view
plain copy

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的函数是否为空,就可以知道对应的类实现是否存在。我们可以这样简单的使用

[cpp] view
plain copy

run_interface("A");  

run_interface("B");  

run_interface("C");  

由于"C"对象不存在,因此,将打印 "factory C is not exist"的信息。

OverloadedFunction

考虑下面的代码

[cpp] view
plain copy

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; 例如

[cpp] view
plain copy

BOOST_TEST(identity_s("abc") == "abc");  

BOOST_TEST(identity_i(123) == 123);  

BOOST_TEST(identity_d(1.23) == 1.23);  

但是,使用OverlaodedFunction,就可以使用统一的名字identity来调用了:

[cpp] view
plain copy

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);  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: