博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ function/bind
阅读量:6279 次
发布时间:2019-06-22

本文共 4973 字,大约阅读时间需要 16 分钟。

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 
4 #include
5 6 struct Foo { 7 Foo(int num) : num_(num) {} 8 9 void print_add(int i) const10 { 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 function32 std::function
f_display = print_num; //function 包装一个参数为int,返回值为void 的函数,定义一个函数对象f_display,并将函数常量赋值给这个对象, 这是对常量函数进行包装。33 f_display(-9);34 35 // store a call to a member function36 std::function
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 object41 std::function
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::bind48 std::function
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 object56 std::function
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 ptr62 std::function
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
4 #include
5 6 #ifndef __BASED_THREAD_H 7 #define __BASED_THREAD_H 8 9 class Thread10 {11 public:12 typedef std::function
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
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
(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
5 #include
6 #include
7 #include
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 Foo21 {22 Foo(int num) : num_(num){}23 24 void print_num(int i)25 {26 std::cout << “print num_ + i = ” << num_ + I <

 综合步骤:

typedef std::function<void(void)> ThreadCallback;

//可将对应格式的函数赋值给ThreadCallback;

——————————————————————————————————

设置类的私有成员:

ThreadCallback callback_;

//通过该类构造函数或者用来赋值的成员函数将外部具体函数或者本类的成员函数注册进来,赋值给 callback_, 然后实际在其他函数中作为此类对象的成员函数来调用。

转载于:https://www.cnblogs.com/jianhui-Ethan/p/4669119.html

你可能感兴趣的文章
git 终端常输入命令
查看>>
前端开发学习笔记(二)
查看>>
JAVA设计模式:状态模式
查看>>
pom.xml
查看>>
快速幂模版
查看>>
JavaScript中的匿名函数及函数的闭包
查看>>
karma + phantom + mocha + sion + chai + nightwatch + selenium2(webdriver) 测试框架学习
查看>>
C#操作EXCEL类
查看>>
用java构造一个带层次的文件目录遍历器
查看>>
BZOJ2095:[POI2010]Bridges(最大流,欧拉图)
查看>>
6.计算字段 ---SQL
查看>>
js 对象深拷贝
查看>>
第二次作业
查看>>
WHERE 与HAVING 区别
查看>>
REUSE_ALV_POPUP_TO_SELECT的使用技巧
查看>>
Codeforces 551 E - GukiZ and GukiZiana
查看>>
Spring用到了那些注解?
查看>>
【转载】关于 .Net 逆向的那些工具:反编译篇
查看>>
编程技术面试的五大要点
查看>>
车炮士胜车双象
查看>>