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模板,它给予我们在调用的方式上更大的弹性。

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

[cpp] view plain copy
  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),调用方式如下:

[cpp] view plain copy
  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,可以继续如下进行抽象定义,不同类型采用相同的调用方法:

[cpp] view plain copy
  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的引用来保存函数对象。考虑下面代码:

[cpp] view plain copy
  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能够正确保存函数对象的状态,可以如下修改代码:

[cpp] view plain copy
  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保存的也是函数对象的引用。

//=====================================================================

• cplusplus.com:http://www.cplusplus.com/reference/functional/function/

• cppreference.com:http://en.cppreference.com/w/cpp/utility/functional/function

std::function简介


• 类模板声明

// MS C++ 2013
template<class _Fty> class function;
template<class _Fty> class function : public _Get_function_impl<_Fty>::type { ... }// GCC 4.8.2
template<typename _Signature>                  class function;
template<typename _Res, typename... _ArgTypes> class function<_Res(_ArgTypes...)>: public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, private _Function_base { ... }

// cplusplus.comtemplate <class T> function;     // undefined
template <class Ret, class... Args> class function<Ret(Args...)>;

• 类模板说明

std::function是一个函数包装器模板,最早来自boost库,对应其boost::function函数包装器。在c++0x11中,将boost::function纳入标准库中。该函数包装器模板能包装任何类型的可调用元素(callable element),例如普通函数和函数对象。包装器对象可以进行拷贝,并且包装器类型仅仅只依赖于其调用特征(call signature),而不依赖于可调用元素自身的类型。

一个std::function类型对象实例可以包装下列这几种可调用元素类型:函数、函数指针、类成员函数指针或任意类型的函数对象(例如定义了operator()操作并拥有函数闭包)。std::function对象可被拷贝和转移,并且可以使用指定的调用特征来直接调用目标元素。当std::function对象未包裹任何实际的可调用元素,调用该std::function对象将抛出std::bad_function_call异常。

• 模板参数说明

以cplusplus.com中描述的原型说明:

T      : 通用类型,但实际通用类型模板并没有被定义,只有当T的类型为形如Ret(Args...)的函数类型才能工作。

Ret   : 调用函数返回值的类型。

Args : 函数参数类型。

std::function详解


• 包装普通函数

#include <iostream>
#include <functional>
using namespace std;int g_Minus(int i, int j)
{return i - j;
}int main()
{function<int(int, int)> f = g_Minus;cout << f(1, 2) << endl;                                            // -1return 1;
}

• 包装模板函数

#include <iostream>
#include <functional>
using namespace std;template <class T>
T g_Minus(T i, T j)
{return i - j;
}int main()
{function<int(int, int)> f = g_Minus<int>;cout << f(1, 2) << endl;                                            // -1return 1;
}

• 包装lambda表达式

#include <iostream>
#include <functional>
using namespace std;auto g_Minus = [](int i, int j){ return i - j; };int main()
{function<int(int, int)> f = g_Minus;cout << f(1, 2) << endl;                                            // -1return 1;
}

• 包装函数对象

非模板类型:

#include <iostream>
#include <functional>
using namespace std;struct Minus
{int operator() (int i, int j){return i - j;}
};int main()
{function<int(int, int)> f = Minus();cout << f(1, 2) << endl;                                            // -1return 1;
}

模板类型:

#include <iostream>
#include <functional>
using namespace std;template <class T>
struct Minus
{ T operator() (T i, T j){return i - j;}
};int main()
{function<int(int, int)> f = Minus<int>();cout << f(1, 2) << endl;                                            // -1return 1;
}

• 包装类静态成员函数

非模板类型:

#include <iostream>
#include <functional>
using namespace std;class Math
{
public:static int Minus(int i, int j){return i - j;}
};int main()
{function<int(int, int)> f = &Math::Minus;cout << f(1, 2) << endl;                                            // -1return 1;
}

模板类型:

#include <iostream>
#include <functional>
using namespace std;class Math
{
public:template <class T>static T Minus(T i, T j){return i - j;}
};int main()
{function<int(int, int)> f = &Math::Minus<int>;cout << f(1, 2) << endl;                                            // -1return 1;
}

• 包装类对象成员函数

非模板类型:

#include <iostream>
#include <functional>
using namespace std;class Math
{
public:int Minus(int i, int j){return i - j;}
};int main()
{Math m;function<int(int, int)> f = bind(&Math::Minus, &m, placeholders::_1, placeholders::_2);cout << f(1, 2) << endl;                                            // -1return 1;
}

模板类型:

#include <iostream>
#include <functional>
using namespace std;class Math
{
public:template <class T>T Minus(T i, T j){return i - j;}
};int main()
{Math m;function<int(int, int)> f = bind(&Math::Minus<int>, &m, placeholders::_1, placeholders::_2);cout << f(1, 2) << endl;                                            // -1return 1;
}

std::cunction() 简单描述相关推荐

  1. sas简单描述统计分析和散点图

    简单描述统计分析 一. means过程 (一)例题和语句分析 例题1:某车间有30个人分成4组,求车间工人平均每小时制作的配件个数 data data3_1; input no w n; /*按自由格 ...

  2. TCP/IP 协议标准简单描述

    TCP/IP 协议标准简单描述 说明 分为三部分:中文名称.缩写.说明. 应用层 DNS 域名服务 (DNS) 功能: 将域名转化为IP地址 BOOTP 引导程序协议 (BOOTP) 功能: 允许无盘 ...

  3. 如果你要实现IOC,请简单描述一下实现步骤?

    如果你要实现IOC,请简单描述一下实现步骤? 实现IOC的步骤: ①定义用来描述bean的配置的Java类. ②解析bean的配置,将bean的配置信息转换为BeanDefinition对象保存到内存 ...

  4. Linux主要的系统目录及其简单描述

    Linux主要的系统目录及其简单描述如下: /sbin: 一般存放非普通用户使用的命令(有时普通用户也可能会用到).目录/usr/sbin中也包括了许多系统命令. /etc:系统的配置文件. /roo ...

  5. 简单描述下微信小程序的相关文件类型?

    简单描述下微信小程序的相关文件类型? 微信小程序项目结构主要有四个文件类型,如下: .WXML 是框架设计的一套标签语言,结合基础组件.事件系统,可以构建出页面的结构.内部主要是微信自己定义的一套组件 ...

  6. 02 食尚年华石锅土鲫鱼需求简单描述

    02 食尚年华石锅土鲫鱼需求简单描述 文章目录 02 食尚年华石锅土鲫鱼需求简单描述 现有情况简述 店主希望实现功能 现有情况简述 食尚年华石锅土鲫鱼是一家餐饮店,目前店内经营采用纯人工方式,顾客进入 ...

  7. 常用HTML标签的英文全称及简单描述

    常用HTML标签的英文全称及简单描述 HTML标签 英文全称 中文释义 a Anchor 锚 abbr Abbreviation 缩写词 acronym Acronym 取首字母的缩写词 addres ...

  8. 带复选框和简单描述的Qt QTreeWidget树形控件的简单使用

    Qt QTreeWidget树形控件的简单使用 具有选择框的树形控件 具有选择框的树形控件 效果:当选中顶层的树形节点时,子节点全部被选中:当取消选中顶层树形节点时,子节点全部被取消:当选中子节点时, ...

  9. Window布局参数简单描述

    Window 布局参数简单描述 文章目录 一.LayoutParams.type 二.LayoutParams.flags 三.Gravity.dimAmount.buttonBrightness.A ...

最新文章

  1. linux 增加回环设备,linux命令练习:mount fdisk swap dd创建本地回环设备
  2. php$pat,PHP的Session管理框架 patSession | 码农软件 - 码农网
  3. 从古希腊神话说起,讲讲英语里的偏旁部首
  4. 应用Java程序片段动态生成下拉列表
  5. C++STL常用算术生成算法
  6. 文房四宝用计算机取代的什么,《文房四宝》阅读练习及答案
  7. Effective Java(一)———— 代替构造器和Setter的构建器模式
  8. [收藏] C#面试基础问题
  9. 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0...
  10. Cinesamples CineOrch for Mac(电影管弦乐队音色库)v2.0特别版
  11. 制衣软件测试自学,服装检验作业指导书.doc
  12. 计算机辅助设计和制造论文,计算机辅助设计与制造CAD-CAM
  13. 使用AudioRecord实现声音采集
  14. 用Python制作模拟人生4 Mod(01)
  15. mysql数据模型三要素_数据模型的作用及三要素是什么?
  16. IT“茫一代”转型记:创业维艰 苦乐皆有
  17. android高德地图关键字搜索,关键字搜索-POI搜索-示例中心-JS API 示例 | 高德地图API...
  18. 微信开发 没有认证过的服务号怎么办?微信提供了测试号(开通了认证过的服务号的功能)
  19. Springboot综合案例锦集
  20. 数据库系统概念 第三章 SQL介绍

热门文章

  1. RT-Thread 模拟器 simulator 搭建 LVGL 的开发调试环境
  2. 音乐机器人特奥_意大利机器人特奥·特罗尼科征服中国观众 Il Robot italiano conquista la Cina...
  3. 作业1:关于使用python中scikit-learn(sklearn)模块,实现鸢尾花(iris)相关数据操作(数据加载、标准化处理、构建聚类模型并训练、可视化、评价模型)
  4. lisp 焊缝标注_基于ObjectARX的焊接符号标注系统开发
  5. HUAWEI华为MateBook X Pro 2020 i7 16GB+512GB (MACHC-WAE9LP)原装出厂系统恢复原厂系统(送解压密码)
  6. 学计算机的人c语言修仙评价,评《C语言修仙》 非渊静者 评《C语言修仙》 时间:2019-05-04 11:55:19...
  7. unhandled system error, NCCL version 2.7.8
  8. 1191 家谱树(拓扑排序)
  9. kubeadm 方式搭建k8s笔记
  10. MVC中集成Hangfire定时任务