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