读书频道 > 网站 > 网页设计 > 深入应用C++11:代码优化与工程级应用
1.5.2 可调用对象包装器——std::function
15-07-07    下载编辑
收藏    我要投稿   
在StackOverflow的最近一次世界性调查中,C++11在所有的编程语言中排名第二, C++11受到程序员的追捧是毫不意外的,因为它就像C++之父Bjarne Stroustrup说的:它看起来就像一门新的语言。C++11新增加了相当多的立即去当当网订购

std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。

下面看一个示例,如代码清单1-17所示。

代码清单1-17 std::function的基本用法

#include <iostream>   // std::cout
#include <functional> // std::function

void func(void)
{
   std::cout << __FUNCTION__ << std::endl;
}

class Foo
{
public:
   static int foo_func(int a)
   {
      std::cout << __FUNCTION__ << "(" << a << ") ->: ";
      return a;
   }
};

class Bar
{
public:
   int operator()(int a)
   {
      std::cout << __FUNCTION__ << "(" << a << ") ->: ";
      return a;
   }
};

int main(void)
{
   std::function<void(void)> fr1 = func; // 绑定一个普通函数
   fr1();

   // 绑定一个类的静态成员函数
   std::function<int(int)> fr2 = Foo::foo_func;
   std::cout << fr2(123) << std::endl;

   Bar bar;
   fr2 = bar;     // 绑定一个仿函数
   std::cout << fr2(123) << std::endl;

   return 0;
}
运行结果如下:
func
foo_func(123) ->: 123
operator()(123) ->: 123

从上面我们可以看到std::function的使用方法,当我们给std::function填入合适的函数签名(即一个函数类型,只需要包括返回值和参数表)之后,它就变成了一个可以容纳所有这一类调用方式的“函数包装器”。

再来看如代码清单1-18所示的例子。

代码清单1-18 std::function作为回调函数的示例

#include <iostream>    // std::cout
#include <functional>    // std::function

class A
{
   std::function<void()> callback_;

public:
   A(const std::function<void()>& f)
      : callback_(f)
   {}

   void notify(void)
   {
      callback_();   // 回调到上层
   }
};

class Foo
{
public:
   void operator()(void)
   {
      std::cout << __FUNCTION__ << std::endl;
   }
};

int main(void)
{
   Foo foo;
   A aa(foo);
   aa.notify();

   return 0;
}

从上面的例子中可以看到,std::function可以取代函数指针的作用。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于C#中特殊的委托(只有一个成员的委托)。

同样,std::function还可以作为函数入参,如代码清单1-19所示。

代码清单1-19 std::function作为函数入参的示例

#include <iostream>   // std::cout
#include <functional> // std::function

void call_when_even(int x, const std::function<void(int)>& f)
{
   if (!(x & 1)) // x % 2 == 0
   {
      f(x);
   }
}

void output(int x)
{
   std::cout << x << " ";
}

int main(void)
{
   for(int i = 0; i < 10; ++i)
   {
      call_when_even(i, output);
   }
   std::cout << std::endl;
   return 0;
}
输出结果如下:
0 2 4 6 8

从上面的例子中可以看到,std::function比普通函数指针更灵活和便利。

在下一节我们可以看到当std::function和std::bind配合起来使用时,所有的可调用对象(包括类成员函数指针和类成员指针)都将具有统一的调用方式。

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站