码迷,mamicode.com
首页 > 编程语言 > 详细

C++ function/bind

时间:2015-07-23 06:38:11      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

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 }

 

C++ function/bind

标签:

原文地址:http://www.cnblogs.com/jianhui-Ethan/p/4669119.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!