boost::function 和 boost::bind 如何工作

2021-12-24 00:00:00 c++ boost boost-bind boost-function

我不喜欢在我的代码中散布魔术盒...这两个类究竟如何工作以允许基本上任何函数映射到函数对象,即使函数<>具有完全不同的参数设置为一个我传递给 boost::bind

I dislike having magic boxes scattered all over my code...how exactly do these two classes work to allow basically any function to be mapped to a function object even if the function<> has a completely different parameter set to the one im passing to boost::bind

它甚至适用于不同的调用约定(即成员方法在 VC 下是 __thiscall,但正常"函数通常是 __cdecl__stdcall对于那些需要兼容 C 的.

It even works with different calling conventions (i.e. member methods are __thiscall under VC, but "normal" functions are generally __cdecl or __stdcall for those that need to be compatible with C.

推荐答案

boost::function 允许任何带有 operator() 和正确签名的东西被绑定为参数,你的绑定结果可以用参数int调用,所以它可以绑定到function.

boost::function allows anything with an operator() with the right signature to be bound as the parameter, and the result of your bind can be called with a parameter int, so it can be bound to function<void(int)>.

它是这样工作的(这个描述同样适用于std::function):

This is how it works (this description applies alike for std::function):

boost::bind(&klass::member, instance, 0, _1) 返回这样的对象

struct unspecified_type
{
  ... some members ...
  return_type operator()(int i) const { return instance->*&klass::member(0, i);
}

其中return_typeint是从klass::member的签名推断出来的,实际上是函数指针和绑定参数存储在对象中,但这并不重要

where the return_type and int are inferred from the signature of klass::member, and the function pointer and bound parameter are in fact stored in the object, but that's not important

现在,boost::function 不做任何类型检查:它将接受您在模板参数中提供的任何对象和任何签名,并创建一个可根据您的签名和调用对象.如果这是不可能的,那就是编译错误.

Now, boost::function doesn't do any type checking: It will take any object and any signature you provide in its template parameter, and create an object that's callable according to your signature and calls the object. If that's impossible, it's a compile error.

boost::function 实际上是一个这样的对象:

boost::function is actually an object like this:

template <class Sig>
class function
{
  function_impl<Sig>* f;
public:
  return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};

其中return_typeargument_type 是从Sig 中提取出来的,f 在堆上动态分配.这需要允许具有不同大小的完全不相关的对象绑定到 boost::function.

where the return_type and argument_type are extracted from Sig, and f is dynamically allocated on the heap. That's needed to allow completely unrelated objects with different sizes bind to boost::function.

function_impl 只是一个抽象类

template <class Sig>
class function_impl
{
public:
  virtual return_type operator()(argument_type arg0) const=0;
};

完成所有工作的类是从boost::function 派生的具体类.您分配给 boost::function

The class that does all the work, is a concrete class derived from boost::function. There is one for each type of object you assign to boost::function

template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
  Object o
public:
  virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};

这意味着在您的情况下,对 boost 函数的赋值:

That means in your case, the assignment to boost function:

  1. 实例化一个类型 function_impl_concrete(当然是编译时间)
  2. 在堆上创建一个该类型的新对象
  3. 将此对象分配给 boost::function 的 f 成员

当您调用函数对象时,它会调用其实现对象的虚函数,从而将调用定向到您的原始函数.

When you call the function object, it calls the virtual function of its implementation object, which will direct the call to your original function.

免责声明:请注意,此解释中的名称是故意编造的.与真实人物或角色的任何相似之处……您知道的.目的是为了说明原理.

DISCLAIMER: Note that the names in this explanation are deliberately made up. Any resemblance to real persons or characters ... you know it. The purpose was to illustrate the principles.

相关文章