• 3.4. Boost.Function

    3.4. Boost.Function

    为了封装函数指针,Boost.Function 提供了一个名为 boost::function 的类。 它定义于 boost/function.hpp,用法如下:

    1. #include <boost/function.hpp>
    2. #include <iostream>
    3. #include <cstdlib>
    4. #include <cstring>
    5.  
    6. int main()
    7. {
    8. boost::function<int (const char*)> f = std::atoi;
    9. std::cout << f("1609") << std::endl;
    10. f = std::strlen;
    11. std::cout << f("1609") << std::endl;
    12. }
    • 下载源代码

    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 异常。

    1. #include <boost/function.hpp>
    2. #include <iostream>
    3.  
    4. int main()
    5. {
    6. try
    7. {
    8. boost::function<int (const char*)> f;
    9. f("");
    10. }
    11. catch (boost::bad_function_call &ex)
    12. {
    13. std::cout << ex.what() << std::endl;
    14. }
    15. }
    • 下载源代码

    注意,将值 0 赋给一个 boost::function 类型的函数指针,将会释放当前所赋的函数。 释放之后再调用它也会导致 boost::bad_function_call 异常被抛出。 要检查一个函数指针是否被赋值某个函数,可以使用 empty() 函数或 operator bool() 操作符。

    通过使用 Boost.Function,类成员函数也可以被赋值给类型为 boost::function 的对象。

    1. #include <boost/function.hpp>
    2. #include <iostream>
    3.  
    4. struct world
    5. {
    6. void hello(std::ostream &os)
    7. {
    8. os << "Hello, world!" << std::endl;
    9. }
    10. };
    11.  
    12. int main()
    13. {
    14. boost::function<void (world*, std::ostream&)> f = &world::hello;
    15. world w;
    16. f(&w, boost::ref(std::cout));
    17. }
    • 下载源代码

    在调用这样的一个函数时,传入的第一个参数表示了该函数被调用的那个特定对象。 因此,在模板定义中的左括号后的第一个参数必须是该特定类的指针。 接下来的参数才是表示相应的成员函数的签名。

    这个程序还使用了来自 Boost.Ref 库的 boost::ref(),它提供了一个方便的机制向 Boost.Function 传递引用。