65.9K
CodeProject 正在变化。 阅读更多。
Home

查看 Boost Bind 和 Function 库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.34/5 (25投票s)

2006年2月9日

4分钟阅读

viewsIcon

101122

downloadIcon

607

对 Boost Bind 和 Function 库的简要介绍。

引言

如果您是一位 C++ 开发者,但尚未熟悉 Boost 库,我鼓励您开始尝试使用它。Boost 包含许多不同的库,涵盖了从泛型编程到内存池管理和智能指针等各个领域。其中许多库都是独立的,因此您可以作为开发者只关注您感兴趣的功能。

这些库是经过同行评审的、可移植的 C++ 代码。这些库是免费的。许可协议允许自由重新分发,满足开源倡议的开源定义。要开始使用,请访问 Boost 库网站 以获取更多详细信息和下载。

在介绍 Bind 和 Function 库之前,还有一点值得一提,那就是所有库都依赖于高级 C++ 功能,例如模板和标准模板库 (STL)。Boost 的设计旨在与 STL 协同工作。在 STL 和 Boost 重叠的领域(例如 Bind 库),最好选择 Boost,它很可能提供更丰富的功能实现。Boost 的许多库已被纳入 C++ 标准库技术报告,这是成为标准一部分的步骤。

Boost::bind 增强了标准库函数 std::bind1stbind2nd 提供的功能。通常,与函数式组合编程相关的语法可能相当令人生畏。Boost::bind 的功能通过标准化的语法暴露,使其能够非常轻松地处理函数对象和函数。其函数适配器简化了您必须编写的代码。您无需担心 ptr_funmem_fun_ref 等适配器的使用。该库增加了 STL 无法实现的功能。

我选择通过实现命令模式来演示 bind 和 function 库的强大功能,并使用了静态多态。动态多态是通过使用抽象基类、类指针和虚函数获得的更常见的机制。静态多态可以通过类模板、函数和仿函数来实现。

在我看来,这种方法的一个主要优点是它可以通过编译器进行验证,而不是运行时检查。

/// command object
class command
{
 private:
   boost::function<void ()> _f;
 public:
   command() {;}
   command(boost::function<void ()> f) : _f(f) {;}

   template <typename T> void setFunction (T t) {_f = t ;}
   void execute()
    {
     if(!_f.empty())
    _f();
    }};

Command 类(如上所示)提供了一种将操作封装在对象中的方法。如定义所示,Command 类包含一个私有数据成员,定义为 boost::function<void ()>boost::function 库提供了函数对象包装器,它们可以作为调用接口和回调机制,比传统的函数指针提供了更安全、更强大的实现。函数声明包括返回类型和函数签名。该库提供了两种语法变体,以支持最广泛的编译器。我使用的是在 MSVC 2005 和 MSVC 2003 下支持的首选语法。

首选语法流畅自然,类似于函数声明。Command 对象中的声明要求一个不带任何参数、返回 void 的函数。顺便说一句,如果我想声明一个返回 int、接受 doubleint 作为参数的函数,我会这样写:boost::function<int (double, int)>

boost::function 在大多数情况下可以用于任何您会使用函数指针的地方。这样做的好处是以更大的内存占用和少量的性能损失为代价。如果我没记错的话,我读过使用这个函数可能需要通过函数指针进行两次额外的调用。

类的其余部分用于支持函数包装器的封装,并提供调用它的方法。有趣的部分在于我们如何初始化函数指针。这就是 boost::bind 发挥作用的地方。

Bind 可用于操作自由函数以及动态分配对象的成员函数。该库在处理函数和函数对象时提供了统一的语法。理解 bind 的关键是占位符的概念。占位符定义为 _1 到 _9,您将它们用在通常使用参数的地方。

假设我们想绑定自由函数 void comm (std::string str) {…}。为此,我们绑定到自由函数,并且由于它期望一个参数,我们使用一个占位符。

(boost::bind(&comm, _1)) (“Isn’t this fun?”);

如果 comm 函数是成员函数,绑定仍然是可能的。您必须考虑为所有非静态成员函数传递隐式的“this”引用。在这种情况下,第一个占位符是成员函数的类实例,然后是前面描述的其他参数。

inFlight fly;
(boost::bind (&comm, _1,_2)) (fly, “Isn’t this fun?”);

在我们的示例程序中,我们需要将 Final 类中的一个成员函数绑定到命令对象中的函数对象包装器。这是通过以下方式实现的:

boost::bind(&Final::decAlt, fa)

通过构造函数,绑定然后被分配给私有成员函数包装器。示例程序的第二部分扩展了这个基本思想,表明当处理动态分配的对象时,一切保持不变。它还说明了 boost::bind 如何与 for_each 等 STL 算法很好地配合。

// PART 2
// create a series of commands and stuff them into a container to be sequenced later
vector<boost::shared_ptr<command> > v;

boost::shared_ptr<command> spCmd1(new 
       command(boost::bind(&Final::incAlt, final)));
boost::shared_ptr<command> spCmd2(new 
       command(boost::bind(&Final::decSpeed, final)));
boost::shared_ptr<command> spCmd3(new 
       command(boost::bind(&Final::decAlt, final)));

v.push_back(spCmd1);
v.push_back(spCmd2);
v.push_back(spCmd3);

// run the command sequence
for_each(v.begin(), v.end(), 
      boost::bind(&command::execute, _1));
return 0;

我希望这个简短的介绍能激发您对 Boost 库的兴趣。作者发现,每一次探索库,我都会发现另一个出色的解决方案。它是 STL 的完美补充。

© . All rights reserved.