function是一组函数对象包装类的模板,实现了一个泛型的回调机制。

引入头文件

#include <functional>
using namespace std;
using namespace std::placeholders;  //bind的时候会用`

参考:http://www.cnblogs.com/hujian/archive/2012/12/07/2807605.html

fuction  bind:http://blog.csdn.net/fjb2080/article/details/7527715

我们可以调用的对象有很多,比如普通函数、函数指针、lanmbda表达式、函数对象和类的成员函数等。

不管采用哪种方式,主要调用形式一样(返回值类型、传递给调用的实参类型),我们就可以使用同一种形式来调用。

这个时候就可以用到function模板,它给予我们在调用的方式上更大的弹性。

请看一下三种不同的函数定义:

  1. int add(int a, int b){
  2. return a+b;
  3. }
  4. auto mod=[](int a, int b){return a%b;};
  5. struct divide{
  6. int operator()(int m, int n){
  7. return m/n;
  8. }
  9. };

这三种都可以使用同一种调用形式,int(int, int),调用方式如下:

  1. function<int(int,int)> func1= add;
  2. function<int(int,int)> func2= divide();
  3. function<int(int,int)> func3= mod;
  4. cout<<func1(5, 6)<<endl;
  5. cout<<func2(5, 6)<<endl;
  6. cout<<func3(5, 6)<<endl;

学会了使用function,可以继续如下进行抽象定义,不同类型采用相同的调用方法:

  1. map<string,function<int(int, int)>> funs =
  2. {
  3. {"+", add},
  4. {"-", std::minus<int>()},//标准库的函数,参数为两个整数,可以参考前一篇博客
  5. {"/", divide()},//类成员函数
  6. {"*", [](int i,int j){return i*j;}},//lambda表达式
  7. {"%", mod},
  8. };
  9. funs["+"](4,6);

以上就是function的简单使用。下面是从另一篇博客转载的,使用function的引用来保存函数对象。考虑下面代码:

  1. class CAdd
  2. {
  3. public:
  4. CAdd():m_nSum(0){NULL;}
  5. int operator()(int i)
  6. {
  7. m_nSum += i;
  8. return m_nSum;
  9. }
  10. int Sum() const
  11. {
  12. return m_nSum;
  13. }
  14. private:
  15. int m_nSum;
  16. };
  17. int main(int argc, const char * argv[])
  18. {
  19. CAdd cAdd;
  20. function<int(int)> funcAdd1 = cAdd;
  21. function<int(int)> funcAdd2 = cAdd;
  22. cout<<funcAdd1(10)<<endl;
  23. cout<<funcAdd2(10)<<endl;
  24. cout<<cAdd.Sum()<<endl;
  25. return 0;
  26. }

上面的输出结果是 10 10 0。我们将同一个函数对象赋值给了两个function,然后分别调用这两个function,但函数中的成员变量的值没有保存,问题在哪里?因为function的缺省行为是拷贝一份传递给它的函数对象,于是f1,f2中保存的都是cAdd对象的拷贝。

C++11提供了ref和cref函数来提供对象的引用和常引用的包装。要是function能够正确保存函数对象的状态,可以如下修改代码:

  1. function<int(int)> funcAdd3 = ref(cAdd);
  2. function<int(int)> funcAdd4 = ref(cAdd);
  3. cout<<funcAdd3(10)<<endl;
  4. cout<<funcAdd4(10)<<endl;
  5. cout<<cAdd.Sum()<<endl;

另外,两个function之间赋值时,如果源function保存的是函数对象的拷贝,则目标function保存的也是函数对象的拷贝。如果源function保存的是对函数对象的引用,则目标function保存的也是函数对象的引用。

最新文章

  1. 关于ubuntu16无线网卡RTL8723BE频繁掉线及信号不足的解决办法
  2. AXUre
  3. PHP 小方法之 显示 今天 昨天 上周 上月 近三月 的时间
  4. paip.提升用户体验--提升java的热部署热更新能力
  5. 20145211 《Java程序设计》第8周学习总结——自在飞花轻似梦
  6. Layout No collapsible
  7. Javascript之三种按钮点击事件
  8. Sublime Text 插件 autoprefixer
  9. 1047 - Neighbor House(简单线性DP)
  10. Repeater绑定数据库
  11. 减小Cookie体积
  12. java排序算法(五):快速排序
  13. java---interrupt、interrupted和isInterrupted的区别
  14. [codeforces 804F. Fake bullions]
  15. SpringBoot-目录及说明
  16. 自定义 绑定响应函数 解除响应函数 .addEventListener 兼容 .attachEvent
  17. 基于geohash6编码实现相邻4、9、16网格合并
  18. PAT 乙级 1069 微博转发抽奖(20) C++版
  19. LOJ-10099(点双联通)
  20. 上传文件夹+php

热门文章

  1. 了解固态硬盘SSD,竟然如此简单!小白也能懂!
  2. JAVA基础数组
  3. bzoj 4026 dC Loves Number Theory 主席树+欧拉函数
  4. 一个简单的java年龄计算器
  5. php第二十五节课
  6. UVA - 1611 Crane (思路题)
  7. [bzoj4027][HEOI2015][兔子与樱花] (树形dp思想+玄学贪心)
  8. [luoguP2701] [USACO5.3]巨大的牛棚Big Barn(DP)
  9. hdu 3062 2-sat
  10. VNC Viewer 设置屏幕分辨率-解决屏幕分辨率问题