函数对象与高级编程
千万不要忘记,在C++中,最好不要只从语言本身来判定,它被设计为可以通过库来弥补本身的缺点
Bind成功的一个关键是采用统一的语法来创建函数对象,以及对应于使用该库的类型只有很少的要求。这种设计使得无需关注如何去写与你的类型一起工作的代码,而只需关注我们最关心的一点,代码如何工作以及它实际上做了什么。
弄明白如何使用bind的关键是,占位符的概念。占位符用于表示提供给结果函数对象的参数,Boost.Bind支持最多九个参数。占位符被命名为_1,_2,直至_9,你要把它们放在你原先放参数的地方。
普通函数与成员函数之间有着非常大的差异,在绑定一个成员函数时,bind表达式的第一个参数必须是成员函数所在类的实例!理解这个规则的最容易的方法是,这个显式的参数将取代隐式的this,被传递给所有的非静态成员函数。
bind总是执行复制。如果你通过值来传递,对象将被复制,这可能对性能有害或者产生不必要的影响。为了避免复制对象,你可以使用boost::ref/boost::cref或者使用指针语义。
正如我们所看到的,没有一个明显的方法来保存我们的绑定器以备后用,我们只知道它们是带有某些(未知)的特征的兼容函数对象。但是,如果使用 Boost.Function, 保存函数用于以后的调用正是那个库要做的,并且它兼容于 Boost.Bind, 可以把绑定器赋值给函数,保存它们并用于以后的调用。这是一个非常有用的概念,它可以用于适配并提高了松耦合。
Lambda 库
Boost.Lambda可以创建直接定义和调用的函数对象,或者把它保存起来晚一些再调用。这与Boost.Bind库所提供的很相似,但Boost.Lambda除了可以进行参数绑定,还有其他功能,增加了控制结构、表达式到函数对象的自动转换,还支持在Lambda表达式中的异常处理。
Lambda库用于解决一个使用标准库算法时常会遇见的问题,即需要为了满足算法的要求而定义很多简单的函数对象。
Function 库
保存函数指针和函数对象,用于后续的调用
boost::function 的缺省行为是复制它要调用的函数对象,这一点很重要。如果这导致不正确的语义,或者如果某些函数对象的复制代价太高,你就必须把函数对象包装在 boost::reference_wrapper 中,那样 boost::function 的复制就会是一个 boost::reference_wrapper 的拷贝,它恰好持有一个到原始函数对象的引用。你无须直接使用 boost::reference_wrapper ,你可以使用另两个助手函数,ref 和 cref。 这两函数返回一个持有到某特定类型的引用或 const 引用的 reference_wrapper。
代价的考虑:与使用函数指针相比,使用 Boost.Function 也有一些缺点,特别是对象大小的增加。显然,一个函数指针只占用一个函数指针的空间大小(这当然了!),而一个 boost::function实例占的空间有三倍大。函数指针在调用时的效率也稍高一些,因为函数指针是被直接调用的,而 Boost.Function 可能需要使用两次函数指针的调用。最后,可能在某些需要与C库保持后向兼容的情形下,只能使用函数指针。
与使用函数指针相比,使用 Boost.Function 有几个优点:通过兼容的函数对象而不是真实的签名放松了对签名的要求;可以使用绑定器,如 Boost.Bind 和 Boost.Lambda;可以在调用函数之前检测函数是否为空,即是否存在目标函数;可以使用带状态的对象而不仅限于无状态函数。这些优点表明了使用 Boost.Function 替代C风格的回调可以解决这类普遍存在的问题。使用 Boost.Function 比使用函数指针要多付出一点点代价,只有这一点小代价是被禁止时,才应该考虑使用函数指针技术。
Signals库
函数和函数对象的灵活多点回调
健壮的触发器及事件处理的机制
兼容于函数对象工厂,如Boost.Bind和Boost.Lambda
Boost.Signals库具体化了信号(signals)和插槽(slots),信号指的是某种可被“抛出”的东西,而插槽是接收该信号的连接者。