本文根据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);



boost function对象的更多相关文章

  1. boost::function的用法

    本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1.  介绍 Boost.Func ...

  2. boost::bind 和 boost::function 基本用法

    这是一篇介绍bind和function用法的文章,起因是近来读陈硕的文章,提到用bind和function替代继承,于是就熟悉了下bind和function的用法,都是一些网上都有的知识,记录一下,期 ...

  3. 以boost::function和boost:bind取代虚函数

    转自:http://blog.csdn.net/Solstice/archive/2008/10/13/3066268.aspx 这是一篇比较情绪化的blog,中心思想是“继承就像一条贼船,上去就下不 ...

  4. [转] boost::function用法详解

    http://blog.csdn.net/benny5609/article/details/2324474 要开始使用 Boost.Function, 就要包含头文件 "boost/fun ...

  5. #include <boost/function.hpp>

    为atoi取别名fun,fun实质上是函数指针 #include <iostream> #include <boost/function.hpp> void main() { ...

  6. [置顶] 编程模仿boost::function和boost::bind

    boost::function和boost::bind结合使用是非常强大的,他可以将成员函数和非成员函数绑定对一个对象上,实现了类似C#的委托机制.委托在许多时候可以替代C++里面的继承,实现对象解耦 ...

  7. boost::function 介绍

    本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1.  介绍 Boost.Func ...

  8. boost::function用法详解

    要开始使用 Boost.Function, 就要包含头文件 "boost/function.hpp", 或者某个带数字的版本,从 "boost/function/func ...

  9. boost::function和boost:bind取代虚函数

    以boost::function和boost:bind取代虚函数 这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function ...

随机推荐

  1. 为什么使用LUT比GAL 节省资源

    为什么使用LUT比GAL 节省资源 A[1:0]    B[1:0]     实现一个比较器,如果A=B输出1 否则输出0 传统的GAL 需要 24= 16个存储单元(ROM)来存储结果数据,实现方法 ...

  2. 开发快很重要——如果只看法语或者产品结果C++似乎很强大,但是参与这个C++的开发过程,就会感觉到这种痛苦(Google也是这个看法)

    开发快很重要——如果只看语法或者产品结果C++似乎很强大,但是参与这个C++的开发过程,就会感觉到这种痛苦,太慢了,太麻烦了,虽然在反复调试和优化之后,最后产品的结果可能还不错. Delphi的最大特 ...

  3. thiscall仅仅应用于“C++”成员函数(this指针存放于CX寄存器,参数从右到左压)

    _stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈.VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上" ...

  4. Microsoft Visual Studio 发展历史

    Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品.VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码管控工具. ...

  5. Sqlite ContentProvider Loader 上下文 对话框

    一.整体工程图 二.activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/re ...

  6. sparkUI使用与扩展

      http://www.jianshu.com/p/8e4c38d0c44e

  7. 网页制作之html基础学习1-简介

    学习网页制作主要分为三大块 1.HTML    超文本标记语言( 全称:Hyper Text  Markup Language) 专门编辑静态网页 2.CSS      网页美化:是HTML控制的样式 ...

  8. Agg vs. Cairo 二维绘图引擎之比较和选择 .

    Agg vs. Cairo 二维绘图引擎之比较和选择 cheungmine 当今时代对于作为二维图形软件开发者, 是幸运的.因为除了Windows GDI/GDI+之外,我们还有很多其他的选择.而且这 ...

  9. yii phpexcel自己主动生成文件保存到server上

    近期再整一个报表任务,每天必须把表导出来按excel格式发送邮件给管理员,利用phpexcel把表保存到server上.然后再通过phpmailer发送就ok. ob_end_clean();     ...

  10. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...