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


83

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

它甚至有不同的调用约定有效(即成员方法都是__thiscallVC之下,但“正常”的功能,通常是__cdecl__stdcall为那些需要与兼容C.



1
不是真的-这个问题是关于绑定和功能的
1800信息

是的,因此,仍然存在如何通过bind(&MyClass :: DoSomething,实例,“ Hello世界”,_1)
火枪手

2
20,000次访问圣牛,这需要放在提升首页上!
unixman83 2011年

Answers:


96

boost::function允许将operator()具有正确签名的带有的任何内容绑定为参数,并且可以使用参数调用绑定的结果int,因此可以将其绑定到function<void(int)>

它是这样工作的(此描述适用于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,函数指针和绑定参数其实都是存储在对象中,但是这并不重要

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

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

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

function_impl 只是一个抽象类

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

完成所有工作的类是从派生的具体类boost::function。分配给每种类型的对象都有一个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功能的分配:

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

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

免责声明:请注意,此说明中的名称是故意构成的。任何与真实人物或角色的相似之处……您都知道。目的是说明原理。


那么struct unspecified_type的内容(即operator()函数中的代码)的内容基本上是根据过去的boost :: bind情况根据逐个案例的基础生成的,以允许任意组合和数量的参数吗?
火枪骑兵

1
不,有operator()模板可处理所有Arities(而不同的模板参数可处理组合)
jpalecek,2009年

在最后一个代码块中,它显示为:arg0) const=0 { return......我以前从未见过。我在一个论坛上找到了一个无法正常运行的示例,该示例中有一条链接到C ++常见问题的后续消息,解释说纯虚函数可以具有主体,但是我无法使用此类语法(clang和gcc)来编译任何代码。
Brian Vandenberg 2013年

我应该稍微澄清一下我的问题:一个纯虚函数可以在声明时=0;与后面给出的主体一起赋给主体(例如void Base::Blah() { /* ... */ })。我猜这只是一个错字。
Brian Vandenberg

@BrianVandenberg:我认为这是符合标准的,尽管毫无意义。
Mooing Duck
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.