在C++98中,可以使用函数指针,调用函数,可以参考之前的一篇文章:类的成员函数指针和mem_fun适配器的用法

 

简单的函数调用

 

对于函数:

void foo(const string &s)
{
cout << s << endl;
}

可以使用:

void (*pFunc) (const string &) = &foo;
pFunc("bar");

现在,我们使用C++的fumction,这个函数的返回值为void,参数为const string &,所以function的模板参数为void (const string&),如下:

function<void (const string&)> f = &foo;
f("bar");

再看另外一个例子:

void foo(int i, double d)
{
cout << i << d << endl;
} int main(int argc, const char *argv[])
{
function<void (int, double)> f = &foo;
f(12, 4.5); return 0;
}

 

 

类的成员函数

 

下列代码:

class Foo
{
public:
void foo(int i) { cout << i << endl; } static void bar(double d) { cout << d << endl; } };

我们知道class的普通成员函数,含有一个隐式参数,而static则不然。

对于foo函数,可以使用C++98使用的mem_fun:

Foo f;
(mem_fun(&Foo::foo))(&f, 123);

现在我们使用function,但是隐式参数如何解决?我们使用bind,这是一种非常强大的函数适配器。使用方法如下:

function<void (int)> pf = bind(&Foo::foo,
&f,
std::placeholders::_1);
pf(345);

std::placeholders::_1叫做占位符,如果使用bind绑定某个值,那么该函数等于该参数消失了。如果需要保留,需要使用占位符占住位置。

在这个例子中,foo原本有两个参数,我们把隐式参数绑定某个对象地址,所以只剩下一个地址。function的模板参数为void ()。

我们也可以将两个全部占住,这样bind和mem_fun的效果是一样的:

function<void (Foo*, int)> pf2 = bind(&Foo::foo,
std::placeholders::_1,
std::placeholders::_2); pf2(&f, 456);

这里注意,_1和_2指的是实际调用的实参位置,所以我们可以通过调换_1和_2的位置实现将int和Foo*两个参数调换。

function<void (int, Foo*)> pf3 = bind(&Foo::foo,
std::placeholders::_2,
std::placeholders::_1); pf3(567, &f);

 

bind的灵活使用

 

下面通过一个更具体的例子,演示bind的用法。

void test(int i, double d, const string &s)
{
cout << "i = " << i << " d = " << d << " s = " << s << endl;
}

基本使用很简单:

function<void (int, double, const string&)> f1 = &test;
f1(12, 3.14, "foo");

1.现在将其转化为function<void (int, double)>类型。

我们分析一下:

string类型的参数消失了,所以我们需要bind一个值

其他int和double位置不变,使用_1和_2占住即可。

我们先使用

using namespace std::placeholders;

方便占位符的使用。代码如下:

function<void (int, double)> f2 =
std::bind(&test,
_1,
_2,
"foo");

2.转化为function<void (double, int, const string &)>

分析:

参数仍为3个,不需要绑定任何值。

int和double的顺序变了,所以_1为double,_2为int,注意占位符指的是实参位置。

代码:

function<void (double, int, const string &)> f3 =
std::bind(&test,
_2,
_1,
_3);

其他例子如下:

//3.void (*)(const string &, int)
function<void (const string &, int)> f4 =
std::bind(&test,
_2,
3.4,
_1); //4. void (*) (const string &, int, double)
function<void (const string&, int, double)> f5
= std::bind(&test,
_2,
_3,
_1); //5. void (*)(int)
function<void (int)> f6 =
bind(&test,
_1,
3.4,
"bar"); //6 void(*)(const string &)
function<void (const string &)> f7 =
bind(&test,
12,
4.5,
_1); //7. void (*)()
function<void()> f8 =
bind(&test,
12,
4.5,
"bar");

 

完毕。

C++11之function模板和bind函数适配器的更多相关文章

  1. C++11 std::function、std::bind和lambda表达式

    参考博客: C++可调用对象详解-https://www.cnblogs.com/Philip-Tell-Truth/p/5814213.html 一.关于std::function与std::bin ...

  2. std::function与std::bind 函数指针

    function模板类和bind模板函数,使用它们可以实现类似函数指针的功能,但却却比函数指针更加灵活,特别是函数指向类 的非静态成员函数时. std::function可以绑定到全局函数/类静态成员 ...

  3. 关于boost::function与boost::bind函数的使用心得

    最近开始写一个线程池,期间想用一个通用的函数模板来使得各个线程执行不同的任务,找到了Boost库中的function函数. Boost::function是一个函数包装器,也即一个函数模板,可以用来代 ...

  4. C/C++ C++ 11 std::function和std::bind用法

    std::bind() std::bind 主要用于绑定生成目标函数,一般用于生成的回调函数,cocos的回退函数都是通过std::bind和std::function实现的.两个点要明白: 1.绑定 ...

  5. JQuery实战中遇到的两个小问题$(document).ready() 、bind函数的参数传递问题

    一.$(document).ready() 与 window.onload的区别 1.执行时间 window.onload 必须等到页面内所有元素(包括图片 css js等)加载完毕后才会执行. $( ...

  6. 理解并手写 bind() 函数

    有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...

  7. c++11 符号修饰与函数签名、函数指针、匿名函数、仿函数、std::function与std::bind

    一.符号修饰与函数签名 1.符号修饰 编译器将c++源代码编译成目标文件时,用函数签名的信息对函数名进行改编,形成修饰名.GCC的C++符号修饰方法如下: 1)所有符号都以_z开头 2)名字空间的名字 ...

  8. 使用C++11的function/bind组件封装Thread以及回调函数的使用

    之前在http://www.cnblogs.com/inevermore/p/4008572.html中采用面向对象的方式,封装了Posix的线程,那里采用的是虚函数+继承的方式,用户通过重写Thre ...

  9. 利用C++11的function和bind简化类创建线程

    问题引出 当在类中需要创建线程时,总是因为线程函数需要定义成静态成员函数,但是又需要访问非静态数据成员这种需求,来做若干重复性的繁琐工作.比如我以前就经常定义一个静态成员函数,然后定一个结构体,结构体 ...

随机推荐

  1. 斗地主(NOIP2015)

    原题传送门 神奇的题目.. 一开始我准备打暴力直接搜答案. 然后发现.. 无限TLE.. 因为O((logN)^14*T)BOOM.. 然后Zxyer告诉可以只DFS顺子...其他的可以一步搞出来.. ...

  2. java基础练习 14

    import java.util.Scanner; public class Fourtheen { /*打印出所有的"水仙花数",所谓"水仙花数"是指一个三位 ...

  3. git的使用02

    接下来我们要将文件交给仓库去托管 如何使用版本库

  4. 高级列表控件ListCtrl关联的MFC中的类:CListCtrl

    高级列表控件ListCtrl关联的MFC中的类:CListCtrl■ 报表样式ListCtrl常用操作:1.添加列标题头:InsertColumn2.获取与设置列宽:GetColumnWidth.Se ...

  5. Appium+python自动化8-Appium Python API【转载】

    前言: Appium Python API全集,不知道哪个大神整理的,这里贴出来分享给大家. 1.contexts contexts(self): Returns the contexts withi ...

  6. 第一章:1-11、在上题的分组交换网中,设报文长度和分组长度分别为x和(p+h)(bit),其中p为分组的数据部分的长度,而h为每个分组所带的控制信息固定长度,与p的大小无关。通信的两端共经过k段链路。链路的数据率为b(bit/s),但传播时延和结点的排队时间均可忽略不计。若打算使总的时延为最小,问分组的数据部分长度p应取为多大?

    <计算机网络>谢希仁著第四版课后习题答案答: 分组个x/p, 传输的总比特数:(p+h)x/p 源发送时延:(p+h)x/pb 最后一个分组经过k-1个分组交换机的转发,中间发送时延:(k ...

  7. ubuntu 安装TensorFlow

    1.安装pip $ sudo apt-get install python-pip python-dev 2.安装 TensorFlow for Python 2.7 # Ubuntu/Linux - ...

  8. Spring:基于配置文件的创建对象的各种方式

    在Spring3.0之前,Spring主要创建对象的方法是基于配置文件的,即在配置文件中为对象进行注册,并且可以在配置文件当中为对象的字段或者称之为属性值进行赋值,接下来首先介绍基于配置文件的创建对象 ...

  9. (26)C#WebService

    一.创建webservice 二.发布webservice 1.正式发布 (1)配置IIS 自己在局域网用的话,只需1,2,3 三步 1:网站的名称,将来IIS里有多个网站时可以方便区分 2:文件的本 ...

  10. 手机APP测试技术-整体测试流程框架

    一  手机APP测试基本思路: 测试计划--测试方案--测试用例--执行: 很多小公司都没有具体的需求,项目时间也比较紧,而且流程也不是很严谨,在这样的情况之下,作为测试的我们,该怎样去对项目进行用例 ...