C++11 std::bind std::function 高级用法 (c++11的新特性)

原文:https://blog.csdn.net/yangjie6898862/article/details/44282037

从最基础的了解,std::bind和std::function

  1. <strong>/*

  2. * File: main.cpp

  3. * Author: Vicky.H

  4. * Email: eclipser@163.com

  5. */

  6. #include <iostream>

  7. #include <functional>

  8. #include <typeinfo>

  9. #include <string.h>

  10. int add1(int i, int j, int k) {

  11. return i + j + k;

  12. }

  13. class Utils {

  14. public:

  15. Utils(const char* name) {

  16. strcpy(_name, name);

  17. }

  18. void sayHello(const char* name) const {

  19. std::cout << _name << " say: hello " << name << std::endl;

  20. }

  21. static int getId() {

  22. return 10001;

  23. }

  24. int operator()(int i, int j, int k) const {

  25. return i + j + k;

  26. }

  27. private:

  28. char _name[32];

  29. };

  30. /*

  31. *

  32. */

  33. int main(void) {

  34. // 绑定全局函数

  35. auto add2 = std::bind(add1, std::placeholders::_1, std::placeholders::_2, 10);

  36. // 函数add2 = 绑定add1函数,参数1不变,参数2不变,参数3固定为10.

  37. std::cout << typeid(add2).name() << std::endl;

  38. std::cout << "add2(1,2) = " << add2(1, 2) << std::endl;

  39. std::cout << "\n---------------------------" << std::endl;

  40. // 绑定成员函数

  41. Utils utils("Vicky");

  42. auto sayHello = std::bind(&Utils::sayHello, utils/*调用者*/, std::placeholders::_1/*参数1*/);

  43. sayHello("Jack");

  44. auto sayHelloToLucy = std::bind(&Utils::sayHello, utils/*调用者*/, "Lucy"/*固定参数1*/);

  45. sayHelloToLucy();

  46. // 绑定静态成员函数

  47. auto getId = std::bind(&Utils::getId);

  48. std::cout << getId() << std::endl;

  49. std::cout << "\n---------------------------" << std::endl;

  50. // 绑定operator函数

  51. auto add100 = std::bind(&Utils::operator (), utils, std::placeholders::_1, std::placeholders::_2, 100);

  52. std::cout << "add100(1, 2) = " << add100(1, 2) << std::endl;

  53. // 注意:无法使用std::bind()绑定一个重载函数

  54. return 0;

  55. }

  56. </strong>

 
  1. <strong>/*

  2. * File: main2.cpp

  3. * Author: Vicky.H

  4. * Email: eclipser@163.com

  5. */

  6. #include <iostream>

  7. #include <typeinfo>

  8. void sayHello() {

  9. std::cout << "Hello world !" << std::endl;

  10. }

  11. int sum(int i, int j, int k) {

  12. return i + j + k;

  13. }

  14. template <typename T>

  15. class Func {

  16. public:

  17. Func(T fun) {

  18. if (!fun) {

  19. throw "fun nullptr";

  20. }

  21. _fun = fun;

  22. }

  23. template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>

  24. R Call(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {

  25. return _fun(a1, a2, a3, a4, a5);

  26. }

  27. template<typename R, typename A1, typename A2, typename A3, typename A4>

  28. R Call(A1 a1, A2 a2, A3 a3, A4 a4) {

  29. return _fun(a1, a2, a3, a4);

  30. }

  31. template<typename R, typename A1, typename A2, typename A3>

  32. R Call(A1 a1, A2 a2, A3 a3) {

  33. return _fun(a1, a2, a3);

  34. }

  35. template<typename R, typename A1, typename A2>

  36. R Call(A1 a1, A2 a2) {

  37. return _fun(a1, a2);

  38. }

  39. template<typename R, typename A1>

  40. R Call(A1 a1) {

  41. return _fun(a1);

  42. }

  43. template<typename R>

  44. R Call() {

  45. return _fun();

  46. }

  47. void Call() {

  48. _fun();

  49. }

  50. private:

  51. T _fun;

  52. };

  53. #include <functional>

  54. template<typename R = void, typename... Args>

  55. class Fn {

  56. public:

  57. Fn(std::function<R(Args...)> fun) : _fun(fun) {

  58. }

  59. R operator()(Args... args) {

  60. return _fun(args...);

  61. }

  62. private:

  63. std::function<R(Args...) > _fun;

  64. };

  65. /*

  66. * 将函数注册到对象中,通过对象直接调用

  67. */

  68. int main(void) {

  69. Func<void(*)() > sayHelloFunc(sayHello);

  70. sayHelloFunc.Call();

  71. Func<int (*)(int, int, int) > sumFunc(sum);

  72. std::cout << "sumFunc.Call<int>(1, 2, 3) : " << sumFunc.Call<int>(1, 2, 3) << std::endl;

  73. std::cout << "\n---------------------------" << std::endl;

  74. Fn<> sayHelloFn(sayHello);

  75. sayHelloFn();

  76. Fn<int, int, int, int> sumFn(sum);

  77. std::cout << "sumFn(1, 2, 3) : " << sumFn(1, 2, 3) << std::endl;

  78. std::cout << "\n---------------------------" << std::endl;

  79. return 0;

  80. }

  81. </strong>

Hello world !
sumFunc.Call<int>(1, 2, 3) : 6

---------------------------
Hello world !
sumFn(1, 2, 3) : 6

---------------------------

上面的例子非常有趣,使用了2种方案,将一个函数,注册到一个对象/仿函数中,并且通过一个对象/仿函数来直接调用调用。
例子显而易见的,第2种方案更佳简洁,并且对传递参数有明确的判断,当参数类型或数量不正确的时候,编译器将导致失败。
这种方案,可以将类的成员变量直接作为函数的参数使用,或者,如我:
http://blog.csdn.net/eclipser1987/article/details/23926395
这篇文章中,无法直接调用脚本函数类,有了好的解决办法。这个我将随后补充。

 
  1. #include <list>

  2. #include <functional>

  3. template<typename... Args>

  4. class Fns

  5. {

  6. private:

  7. std::list<std::function<void(Args...)> > _calls;

  8. public:

  9. virtual ~Fns()

  10. {

  11. _calls.clear();

  12. }

  13. void connect(std::function<void(Args...)> fct)

  14. {

  15. _calls.push_back(fct);

  16. }

  17. template<typename Object>

  18. void connect(Object* object, void (Object::*method)(Args...))

  19. {

  20. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});

  21. }

  22. template<typename Object>

  23. void connect(Object* object, void (Object::*method)(Args...) const)

  24. {

  25. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});

  26. }

  27. template<typename Object>

  28. void connect(const Object* object, void (Object::*method)(Args...) const)

  29. {

  30. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});

  31. }

  32. void emit(Args... args)

  33. {

  34. for(auto call : _calls)

  35. call(args...);

  36. }

  37. };

 
  1. #include <cstdio>

  2. #include "Signal.hpp"

  3. class Foo

  4. {

  5. public:

  6. void bar(int x, int y)

  7. {

  8. printf("Foo::bar(%d, %d)\n", x, y);

  9. }

  10. };

  11. void foobar(int x, int y)

  12. {

  13. printf("foobar(%d, %d)\n", x, y);

  14. }

  15. int main(void)

  16. {

  17. Foo foo;

  18. Fns<int, int> s;

  19. // Connect a function

  20. s.connect(foobar);

  21. // Connect a class method

  22. s.connect(&foo, &Foo::bar);

  23. // Create and connect some lambda expression

  24. s.connect([&foo](int x, int y){

  25. printf("lambda::"); foo.bar(x, y);

  26. });

  27. // Emit the signal !

  28. s.emit(4, 2);

  29. getchar();

  30. return 0;

  31. }

foobar(4, 2)
Foo::bar(4, 2)
lambda::Foo::bar(4, 2)

C++11 std::bind std::function 高级用法相关推荐

  1. C++11 std::function, std::bind, std::ref, std::cref

    C++11 std::function, std::bind, std::ref, std::cref 转自:http://www.jellythink.com/ std::function 看看这段 ...

  2. 【C++】C++11的std::function和std::bind用法详解

    在设计回调函数的时候,无可避免地会接触到可回调对象.在C++11中,提供了std::function和std::bind两个方法来对可回调对象进行统一和封装. 可调用对象 C++中有如下几种可调用对象 ...

  3. std::function和std::bind

    std::function和std::bind std::function 可调用对象 是一个函数指针 是一个具有operator()成员函数的类和对象 可被转换成函数指针的类对象: 一个类成员函数指 ...

  4. 函数对象,lamdda表达式,function函数包装,std::bind函数绑定

    一 函数对象 在学习其他知识之前,先来学习函数对象,然后引出std::lambda.std::function.std::bind等内容的学习,那么究竟什么是函数对象呢? 函数对象(Function ...

  5. 【C++】char uchar string stringstream queue array vector set map std::function std::bind

    文章目录 cout 防止使用科学计数法 一维数组的三种初始化方法 二维数组 vector作为参数的三种传参方式 vector 的 reserve resize set std::map std::pa ...

  6. c++11 std::bind与std::function

     function模板类和bind模板函数,使用它们可以实现类似函数指针的功能,但却比函数指针更加灵活,特别是函数指向类的非静态成员函数时. std::function可以绑定到全局函数/类静态成 ...

  7. std::function和std::bind用法

    std::bind() std::bind 主要用于绑定生成目标函数,一般用于生成的回调函数,cocos的回退函数都是通过std::bind和std::function实现的.两个点要明白: 1.绑定 ...

  8. C++11新特性之std::function std::bind

    std::function 在c++98&03时我们通常使用回调函数来处理一些需要某种场景下才触发的回调操作,但回调函数有一个限制就是它只能赋值给同类型的全局或者静态函数,对于其他有相同的返回 ...

  9. C++11 FAQ中文版:std::function 和 std::bind

    std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理函数及函数参数.bind()接受一个函数(或者 ...

最新文章

  1. Apache Kafka-消费端_顺序消费的实现
  2. 袁隆平等专家联袂直播 启动农民丰收节交易会消费季活动
  3. Promise的基本使用
  4. 【中部武汉】理想离家并不遥远
  5. java读取文件指定内容_Java读取文本指定的某一行内容
  6. Spring学习笔记:尝试Lombok简化实体类代码
  7. java多进程_Java中创建多进程
  8. 外星人显卡拓展坞支持linux,今天,你给信仰充值了么?ALIENWARE 外星人 显卡扩展坞 简单开箱...
  9. LeetCode 41. 缺失的第一个正数 First Missing Positive
  10. CSS实现div竖向排版
  11. c语言压缩存储,数据的压缩存储与解压缩算法实现(C语言)
  12. 解决TypeError: Converting circular structure to JSON
  13. 工厂仪表定时拍照智能AI算法识别内网部署方案
  14. javascript--经典实例锦集
  15. HyperLPR车牌识别库代码分析(12)
  16. 对「曲线拟合」和「最小二乘法」的个人理解
  17. The Tomcat connector configured to listen on port 8082 failed to start
  18. IPhone8 升级变砖复活记
  19. Windows安装MySQL报错:由于找不到msvcr120.dll无法继续执行代码
  20. 服务器c盘虚拟内存取消不掉,虚拟内存没用就关掉吧

热门文章

  1. 服务器硬盘坏道修复教程视频,硬盘坏道修复工具 操作教程
  2. php redis 密码,redis如何设置密码
  3. 软件测试_单元测试反模式,完整列表
  4. 故障模块名称kernelbase.dll_固定资产管理系统_资产分类名称(通讯导航有线电及测量仪器篇)...
  5. 戴尔怎样把计算机放在桌面,戴尔台式机桌面图标不见了怎么办
  6. 皮一皮:为啥年轻人不生孩子?
  7. 这可能是对 IOC 和 DI 解释的最清楚的一篇文章了!
  8. 后端进阶,要搞懂哪几块?
  9. 字节跳动每一轮都会考算法吗?已拿Offer的兄弟分享经验!
  10. 面试:说说Java中的 volatile 关键词?