3.4. Boost.Function
为了封装函数指针,Boost.Function 提供了一个名为 boost::function
的类。 它定义于 boost/function.hpp
,用法如下:
- #include <boost/function.hpp>
- #include <iostream>
- #include <cstdlib>
- #include <cstring>
- int main()
- {
- boost::function<int (const char*)> f = std::atoi;
- std::cout << f("1609") << std::endl;
- f = std::strlen;
- std::cout << f("1609") << std::endl;
- }
boost::function
可以定义一个指针,指向具有特定签名的函数。 以上例子定义了一个指针 f,它可以指向某个接受一个类型为 const char*
的参数且返回一个类型为 int
的值的函数。 定义完成后,匹配此签名的函数均可赋值给这个指针。 这个例程就是先将 std::atoi()
赋值给 f,然后再将它重赋值为 std::strlen()
。
注意,给定的数据类型并不需要精确匹配:虽然 std::strlen()
是以 std::sizet
作为返回类型的,但是它也可以被赋值给 _f。
因为 f 是一个函数指针,所以被赋值的函数可以通过重载的 operator()()
操作符来调用。 取决于当前被赋值的是哪一个函数,在以上例子中将调用 std::atoi()
或 std::strlen()
。
如果 f 未赋予一个函数而被调用,则会抛出一个 boost::bad_function_call
异常。
- #include <boost/function.hpp>
- #include <iostream>
- int main()
- {
- try
- {
- boost::function<int (const char*)> f;
- f("");
- }
- catch (boost::bad_function_call &ex)
- {
- std::cout << ex.what() << std::endl;
- }
- }
注意,将值 0 赋给一个 boost::function
类型的函数指针,将会释放当前所赋的函数。 释放之后再调用它也会导致 boost::bad_function_call
异常被抛出。 要检查一个函数指针是否被赋值某个函数,可以使用 empty()
函数或 operator bool()
操作符。
通过使用 Boost.Function,类成员函数也可以被赋值给类型为 boost::function
的对象。
- #include <boost/function.hpp>
- #include <iostream>
- struct world
- {
- void hello(std::ostream &os)
- {
- os << "Hello, world!" << std::endl;
- }
- };
- int main()
- {
- boost::function<void (world*, std::ostream&)> f = &world::hello;
- world w;
- f(&w, boost::ref(std::cout));
- }
在调用这样的一个函数时,传入的第一个参数表示了该函数被调用的那个特定对象。 因此,在模板定义中的左括号后的第一个参数必须是该特定类的指针。 接下来的参数才是表示相应的成员函数的签名。
这个程序还使用了来自 Boost.Ref 库的 boost::ref()
,它提供了一个方便的机制向 Boost.Function 传递引用。