C++ function/bind

function/bind

1. std::function

i.  是一个函数的包装器

ii. std::function<R(T1, T2, ..., TN)>

iii. 这是一个模板实现的函数对象类,它可以包装其它任意的函数对象,而被包装的函数对象具有类型为T1,T2,…,TN的参数,其返回值为R类型

iv. function 对象的最大用处在于实现函数回调

2. bind

i.   bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体(可用实体 就是 函数对象)

ii.  绑定的参数的个数不受限制

iii. 绑定的具体哪些参数也不受限制,由用户指定

iv. bind预先绑定的参数需要传具体的变量或值进去,是pass-by-value(值传递)的

v.  对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增

vi. bind的返回值是可调用实体(也即 函数对象),可以直接赋给std::function对象.

 1 function.cc
 2
 3 #include <functional>
 4 #include <iostream>
 5
 6 struct Foo {
 7 Foo(int num) : num_(num) {}
 8
 9 void print_add(int i) const
10  {
11 std::cout << num_+i << ‘\n‘;
12      }
13
14     int num_;
15 };
16
17 void print_num(int i)
18 {
19     std::cout << i << ‘\n‘;
20 }
21
22 struct PrintNum {
23     void operator()(int i) const  //重载() 符号运算符
24     {
25         std::cout << i << ‘\n‘;
26     }
27 };
28
29 int main()
30 {
31     // store a free function
32     std::function<void(int)> f_display = print_num;  //function 包装一个参数为int,返回值为void 的函数,定义一个函数对象f_display,并将函数常量赋值给这个对象, 这是对常量函数进行包装。
33 f_display(-9);
34
35  // store a call to a member function
36     std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;   //把Foo的成员函数赋值给函数对象f_add_display,这是对成员函数进行包装。
37     const Foo foo(314159);
38 f_add_display(foo, 1);  //foo传的是一个this 指针。
39
40  // store a call to a function object
41     std::function<void(int)> f_display_obj = PrintNum();  //对函数对象进行包装,后面的括号必须要加,表示一个函数。
42     f_display_obj(18);
43
44 //-------------------------------bind----------------------------------
45 //bind函数 可以预先传入函数的参数,即预先绑定参数,后续要传的参数std::placeholder::_1代替。
46
47     // store the result of a call to std::bind
48     std::function<void()> f_display_31337 = std::bind(print_num, 31337);
49 f_display_31337();
50
51 //以前没用function时,可以使用 auto 进行自动推断:
52 //auto  f_display_31337 = std::bind(print_num, 31337);
53 //f_display_31337();
54
55     // store a call to a member function and object
56 std::function<void(int)> f_add_display2= std::bind( &Foo::print_add, foo, std::placeholders::_1 );
57 //这里使用了占位符; 当要用function包装一个成员函数时,要把this指针一同传进去,如第2个函数;但是当使用bind 之后,可以预先的将this指针绑定到函数中,就不能单独添加this指针,它直接将一个对象作为参数。
58 f_add_display2(2);
59
60
61     // store a call to a member function and object ptr
62     std::function<void(int)> f_add_display3= std::bind( &Foo::print_add, &foo, std::placeholders:: _1 );
63     f_add_display3(3);
64  }

//之前(6/30)封装Thread的时候,是采用面向对象的方式。每一次当要执行一个线程的时候都要继承一个Thread类,然后再去把他的虚函数run实现,将他的具体任务留给派生类去实现,实现一个多态的形式。

当有了function 和bind之后,我们就可以用另外一种方式实现多态。

(这是基于对象的一种写法)

 1 Thread.h
 2
 3 #include<pthread.h>
 4 #include<functional>
 5
 6 #ifndef __BASED_THREAD_H
 7 #define __BASED_THREAD_H
 8
 9 class Thread
10 {
11 public:
12     typedef std::function<void(void)> ThreadCallback;   //这里定义的是一个function函数对象,只要满足模型void(void),都可以将函数对象赋给它。
13
14 public:
15     Thread(ThreadCallback callback);  //自定义构造函数的声明,参数是一个函数对象
16     ~Thread();
17
18     void start();
19     void join();
20
21     static void *runThread(void *);
22     bool isRunning() const;
23
24 private:
25     pthread_t pthId_;
26     bool isRunning_;
27     ThreadCallback callback_;  //通过构造函数将外部具体的函数对象注册进来,赋值给callback_. 然后实际在runThread()函数里去调用callback_这个方法。
28 };
29 #endif
 1 Thread.cc
 2
 3 #include “Thread.h”
 4 #include<iostream>
 5
 6 Thread::Thread(ThreadCallback callback)    //自定义构造函数的定义
 7     : pthId_(0),
 8     isRunning_(false),
 9     callback_(callback)
10 {
11     std::cout << “Thread::Thread() ” << std::endl;
12 }
13
14 Thread::~Thread()
15 {
16     pthread_detach(pthId_);
17     isRunning_ = false;
18 }
19
20 void Thread::start()
21 {
22     pthread_create(&pthId_, NULL, runInThread, this);  //创建线程,调用启动函数runInThread().
23     isRunning_  = true;
24 }
25
26 void Thread::join()
27 {
28     pthread_join(pthId_, NULL);
29     isRunning_ = false;
30 }
31
32 void * Thread::runInThread(void *arg)
33 {
34     Thread *pThread = static_cast<Thread *>(arg);  //显示转换
35     pThread->callback_();  //callback_()函数是创建pThread对象的时候注册来的
36     //是通过构造函数将外部具体的函数对象注册进来,赋值给callback_. 然后实际在runThread()函数里去调用callback_这个方法。
37 }
38
39 bool Thread::isRunning() const
40 {
41     return isRunning_;
42 }
 1 test_main.cc
 2
 3 #include “Thread.h”
 4 #incldue<unistd.h>
 5 #include<time.h>
 6 #include<stdlib.h>
 7 #include<iostream>
 8
 9 void print_num(void)  //与Thread头文件中function绑定的函数类型是一样的。
10 {
11     ::srand(time(NULL));
12     while(1)
13     {
14         int inum = ran() %100;
15         std::cout << “print a num: ” << inum << std::endl;
16         sleep(1);
17 }
18 }
19
20 struct Foo
21 {
22     Foo(int num) : num_(num){}
23
24 void print_num(int i)
25 {
26     std::cout << “print num_ + i = ” << num_ + I <<std::endl;
27 }
28
29 int num_;
30 };
31
32 int main(void)
33 {
34     //情况一:
35     Thread thread(print_num);   //创建Thread对象,调用自定义的构造函数; 注册回调函数print_num。
36
37     //情况二:
38     Foo foo(10);
39     Thread thread(std::bind(&Foo::print_num, foo, 20));
40 //bind 函数返回一个绑定好参数的函数对象。
41
42     thread.start();
43     thread.join();
44
45     return 0;
46 }
时间: 2024-10-17 09:02:57

C++ function/bind的相关文章

【转帖】漫话C++0x(四) —- function, bind和lambda

实在是觉得此文总是去翻感觉不太好.于是果断转过来了,想看原文的请戳:http://www.wuzesheng.com/?p=2032 本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制.之所以把这三块放在一起讲,是因为这三块之间有着非常密切的关系,通过对比学习,加深对这部分内容的理解.在开始之间,首先要讲一个概念,closure(闭包),这个概念是理解lambda的基础.下面我们来看看wikipedia上对于计算机领域的closu

function/bind 函数适配器

1.function/bind简介 function是一种类模板,重载了operator()函数调用操作符,所以每一个function类的对象都是一个函数对象. bind是一种函数适配器,可以改变参数的个数.顺序. 2.相关代码 1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <functional> 5 using namespace std; 6 7 voi

Extjs使用Ext.function.bind, 给句柄函数传参

回调函数updateImage中的key参数,在外部调用时有程序员自己指定. 使用Ext.Function.bind(this.updateImage, this, 'imageUrl', true) 参数一:updateImage函数引用, 参数二:this(固定写法) 参数三:程序员自定义updateImage函数引用中的key参数值 参数四:true (固定写法) showSelectImageWindow: function() { var me = this.getView(); th

javascript 中 function bind()

Function bind() and currying <%-- All JavaScript functions have a method called bind that binds to an object and returns a new function. The first argument to bind sets the this context of the function. function area (height) { return this.width * he

function bind()

function t(){alert(this.a);} t() var t2 = t.bind({a:2}) t2() t.call({a:2}) bind()的实现原理.用处   待整理 function bind()

function/bind的救赎(上)

这是那篇C++0X的正文.太长,先写上半部分发了. Function/bind可以是一个很简单的话题,因为它其实不过就是一个泛型的函数指针.但是如果那么来谈,就没意思了,也犯不上写这篇东西.在我看来,这个事情要讲的话,就应该讲透,讲到回调(callback).代理(delegate).信号(signal)和消息传递(messaging)的层面,因为它确实是太重要了.这个话题不但与面向对象的核心思想密切相关,而且是面向对象两大流派之间交锋的中心.围绕这个问题的思考和争论,几乎把20年来所有主流的编

C++ TR1 Function Bind

在C++ 11出现以前,C++的事件一般是通过回调形试来实现,如 void (*func)(int,int,int),其实际上是一种函数指针,在C中调用时是直接写函数名在参数列表中,而在C++中,大部份的回调需要定义成 static.也就是静态函数.通过::作用域符,方式调用. 当然在C++TR11出现前,更早的function 与Bind 在开源库中boost 中就有,而C++11 tr1也就是借鉴了或者直接使用了boost库中的相关模板. 现在就来说说C++ tr1 中的Function 模

为什么React事件处理函数必须使用Function.bind()绑定this?

最近在React官网学习Handling Events这一章时,有一处不是很明白.代码如下: class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleC

ES6下的Function.bind方法

在JavaScript的使用中,this的指向问题始终是一个难点.不同的调用方式,会使this指向不同的对象.而使用call,apply,bind等方式,可改变this的指向,完成一些令人惊叹的黑魔法 最近了解了一下Function对象下的bind方法,同时对JavaScript对象下this指向,call,apply等方法有了更深刻的了解 function.apply(thisArg,[argsArray]) thisArg: function函数运行时的this值 argsArray: 一个