在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. 2590: [Usaco2012 Feb]Cow Coupons

    2590: [Usaco2012 Feb]Cow Coupons Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 306  Solved: 154[Su ...

  2. 翻煎饼_简单模拟_C++

    一.题目描述(懒人可直接跳过看题目概述) 题目来源: SWUST OJ  题目0254 http://acm.swust.edu.cn/problem/0254/ 二.问题概述 给出一列数,每次可将包 ...

  3. 牧场行走(LCA)

    神奇传送门 好吧,这题很有意思.. 第一眼撇的时候还以为是(SPFA)呜.... 然后发现要Q次询问就想到了LCA 但是发现不是求LCA.. 于是想到了一个神奇的定律: 两点的LCA一定在u到v的最短 ...

  4. UVALIVE 3645 Objective: Berlin

    最大流 .以航班为节点进行最大流. 容量限制进行拆点. 如果时间地点满足可以建一条边. 具体看代码.变量名被修改过了.一开始的变量名可能比较容易看懂 但CE了.可能与库里的变量重复了. AC代码 #i ...

  5. android与java的关系

    摘自:http://bbs.51cto.com/thread-944897-1.html   相信学习android的人都会想过或者想知道这个问题,那就请你耐心的看完这篇文章吧,你会对android与 ...

  6. Appium+python自动化17-启动iOS模拟器APP源码案例【转载】

    前言 上一篇已经可以启动iOS模拟器上的safari浏览器了,启动app比启动浏览器要复杂一点,本篇以github上的源码为案例详细介绍如何启动iOS模拟器的app 一.clone源码 1.githu ...

  7. Flask-宏的相关知识。

    转自ITOYO:XIAOJINGJING Jinja2的宏功能有些类似于传统程序语言中的函数,既然是函数就有其声明和调用两个部分. 首先声明一个宏: <html lang="en&qu ...

  8. 网易 监控 openstack

    http://www.360doc.com/content/16/0416/08/13792507_551022987.shtml

  9. [BZOJ1054][HAOI2008]移动玩具 bfs+hash

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2432  Solved: 1355[Submit][Stat ...

  10. jmeter引用cookies进行登录实战

    以jmeter登录接口为例,就下面的这个登录页面 在测试之前,我们输入用户和密码先手动登录下,看看有那些网络信息,使用fiddler抓包 登录发送的是这个请求,我们看下使用什么方式,以及用到那些参数 ...