在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. mac使用基础

    Mac 系统的桌面 Mac 的桌面是一个很炫的3D, 背景是一张“星空”图. 2 Dock:  在桌面的下方有一排图标, 叫Dock, 用来快速启动程序, 进入文件夹, 它同时还可以停靠正在运行的程序 ...

  2. andrio

    ## 以eclipse -clean命令从命令行启动 eclipse ## 配置Android模拟器 点击上图右边的按钮(像个手机一样的),打开AVD管理器后,点击 New 新建一个模拟器,输入Nam ...

  3. poj 1329(已知三点求外接圆方程.)

    Circle Through Three Points Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3766   Acce ...

  4. hdu 3635(并查集)

    Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  5. RANSAC中迭代次数的计算

    假设 $w=\frac{内点个数 }{所有点的个数}$. 则 $p_{0}=w^n$表示采样的$n$个点全为内点的概率(可重复) 则至少有一个为外点的概率$p_{1}=1-p_{0}$ 则重复$K$次 ...

  6. js 抽奖小案例

    Luck Draw 在线演示:九宫格抽奖 对九宫格形式的抽奖页面进行了一些简单封装.以后有机会再更新其他形式的抽奖.

  7. CF978E Bus Video System【数学/前缀和/思维】

    [链接]: CF [分析]: 设上车前人数 x ,中途最大人数为 x+max ,最小人数为 x+min (max≥0,min≤0) 可得不等式组 x+max≤w, x+min≥0 整数解个数为 max ...

  8. 51nod 1090 3个数和为0【二分】

    1090 3个数和为0 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等.从 ...

  9. Python与数据库[1] -> 数据库接口/DB-API[2] -> SQL Server 适配器

    SQL_Server适配器 / SQL_Server Adapter 1 环境配置 / Environment Configuration 安装SQL_Server的Python适配器包 pip in ...

  10. FZU-2268 Cutting Game(二进制使用)

     Problem 2268 Cutting Game Accept: 254    Submit: 605Time Limit: 1000 mSec    Memory Limit : 32768 K ...