• c++函数指针 回调函数


     

    目录

    函数指针

    ​编辑

    实例

    函数指针作为某个函数的参数

    实例

     std::function轻松实现回调函数

    绑定一个函数

    作为回调函数

     作为函数入参



    函数指针

    函数指针是指向函数的指针变量。

    通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。

    函数指针可以像一般函数一样,用于调用函数、传递参数。

    函数指针类型的声明:

    typedef type (*fun_ptr)(type,type); // 声明一个指向同样参数、返回值的函数指针类型
    

    实例

    以下实例声明了函数指针变量 p,指向函数 max:

    1. #include
    2. #define _CRT_SECURE_NO_WARNINGS
    3. typedef int(*func_ptr)(int, int);
    4. int max(int x, int y)
    5. {
    6. return x > y ? x : y;
    7. }
    8. int main(void)
    9. {
    10. //p是指向max的函数指针
    11. func_ptr p = &max;//也可以写成 func_ptr p = max;
    12. int a, b, c, d;
    13. printf("请输入三个数字:");
    14. scanf("%d %d %d", &a, &b, &c);
    15. /* 与直接调用函数等价,d = max(max(a, b), c) */
    16. d = p(p(a, b), c);
    17. printf("最大的数字是: %d\n", d);
    18. return 0;
    19. }

    函数指针作为某个函数的参数

    函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

    简单讲:回调函数是由别人的函数执行时调用你实现的函数。

    以下是来自知乎作者常溪玲的解说:

    你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

    实例

    实例中 populate_array() 函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。

    实例中我们定义了回调函数 getNextRandomValue(),它返回一个随机值,它作为一个函数指针传递给 populate_array() 函数。

    populate_array() 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。

    1. #include
    2. #include
    3. void populate_array(int* array, size_t arraySize, int (*getNextValue)(void))
    4. {
    5. for (size_t i = 0; i < arraySize; i++)
    6. array[i] = getNextValue();
    7. }
    8. // 获取随机值
    9. int getNextRandomValue(void)
    10. {
    11. return rand();
    12. }
    13. int main(void)
    14. {
    15. int myarray[10];
    16. populate_array(myarray, 10, getNextRandomValue);//函数的名称就是函数的地址
    17. for (int i = 0; i < 10; i++) {
    18. printf("%d ", myarray[i]);
    19. }
    20. printf("\n");
    21. return 0;
    22. }

     std::function轻松实现回调函数

    1. #include
    2. #include
    3. struct Foo
    4. {
    5. Foo(int num) : num_(num) {}
    6. void print_add(int i) const { std::cout << num_ + i << '\n'; }
    7. int num_;
    8. };
    9. void print_num(int i)
    10. {
    11. std::cout << i << '\n';
    12. }
    13. struct PrintNum
    14. {
    15. void operator()(int i) const
    16. {
    17. std::cout << i << '\n';
    18. }
    19. };
    20. int main()
    21. {
    22. // store a free function
    23. std::function<void(int)> f_display = print_num;
    24. f_display(-9);
    25. // store a lambda
    26. std::function<void()> f_display_42 = []() { print_num(42); };
    27. f_display_42();
    28. // store the result of a call to std::bind
    29. std::function<void()> f_display_31337 = std::bind(print_num, 31337);
    30. f_display_31337();
    31. // store a call to a member function
    32. std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
    33. const Foo foo(314159);
    34. f_add_display(foo, 1);
    35. f_add_display(314159, 1);
    36. // store a call to a data member accessor
    37. std::function<int(Foo const&)> f_num = &Foo::num_;
    38. std::cout << "num_: " << f_num(foo) << '\n';
    39. // store a call to a member function and object
    40. using std::placeholders::_1;
    41. std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
    42. f_add_display2(2);
    43. // store a call to a member function and object ptr
    44. std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
    45. f_add_display3(3);
    46. // store a call to a function object
    47. std::function<void(int)> f_display_obj = PrintNum();
    48. f_display_obj(18);
    49. auto factorial = [](int n)
    50. {
    51. // store a lambda object to emulate "recursive lambda"; aware of extra overhead
    52. std::function<int(int)> fac = [&](int n) { return (n < 2) ? 1 : n * fac(n - 1); };
    53. // note that "auto fac = [&](int n) {...};" does not work in recursive calls
    54. return fac(n);
    55. };
    56. for (int i{5}; i != 8; ++i)
    57. std::cout << i << "! = " << factorial(i) << "; ";
    58. std::cout << '\n';
    59. }

    绑定一个函数

    1. #include
    2. #include
    3. //普通函数
    4. void func(void)
    5. {
    6. std::cout << __FUNCTION__ << std::endl;
    7. }
    8. //静态类成员函数
    9. class Foo
    10. {
    11. public:
    12. static int foo_func(int a)
    13. {
    14. std::cout << __FUNCTION__ << "(" << a << ") ->:";
    15. return a;
    16. }
    17. };
    18. int main(void)
    19. {
    20. std::function<void(void)> fr = func;
    21. fr();
    22. std::function<int(int)> fr1 = Foo::foo_func;
    23. std::cout << fr1(456) << std::endl;
    24. }

    作为回调函数

    1. #include
    2. #include
    3. class A
    4. {
    5. std::function<void()> callback_;
    6. public:
    7. A(const std::function<void()>& f) :callback_(f) {};
    8. void notify(void)
    9. {
    10. callback_();
    11. }
    12. };
    13. class Foo {
    14. public:
    15. void operator()(void)
    16. {
    17. std::cout << __FUNCTION__ << std::endl;
    18. }
    19. };
    20. int main(void)
    21. {
    22. Foo foo;
    23. A aa(foo);
    24. aa.notify();
    25. }

     作为函数入参

    1. #include
    2. #include
    3. void call_when_even(int x, const std::function<void(int)>& f)
    4. {
    5. if (!(x & 1))
    6. {
    7. f(x);
    8. }
    9. }
    10. void output(int x)
    11. {
    12. std::cout << x << " ";
    13. }
    14. int main(void)
    15. {
    16. for (int i = 0; i < 10; ++i)
    17. {
    18. call_when_even(i, output);
    19. }
    20. std::cout << std::endl;
    21. }

    一些AI给出的回答

    `std::function`是C++标准库中的一个通用、可调用、多态的函数封装器,可以用来存储任何可调用对象的引用,如函数指针、函数对象、Lambda表达式等。它的主要作用是将函数作为参数传递,实现回调函数的功能。

    下面是一个简单的实例,演示了如何使用`std::function`存储一个函数,并调用它:` 

     

    在这个例子中,我们定义了

    1. #include
    2. #include
    3. void print_hello() {
    4.     std::cout << "Hello, world!" << std::endl;
    5. }
    6. int main() {
    7.     std::function<void()> func = print_hello;
    8.     func();
    9.     return 0;
    10. }

    一个名为`print_hello`的函数,用于打印"Hello, world!"。然后,我们创建了一个`std::function`类型的变量`func`,并将`print_hello`函数的地址赋值给`func`。最后,我们调用`func`,输出"Hello, world!"。

    在C++中,`std::function`是一个通用、可调用、多态的函数封装器,可以用来存储任何可调用对象的引用,如函数指针、函数对象、Lambda表达式等。`std::function`的模板参数`T`表示存储的函数的参数类型,当`T`是一个函数指针类型时,`std::function`可以用来存储一个函数指针;当`T`是一个函数对象类型时,`std::function`可以用来存储一个函数对象;当`T`是一个Lambda表达式类型时,`std::function`可以用来存储一个Lambda表达式。

    下面是一些例子:

    1. // 存储一个接受两个int参数的函数
    2. std::function<int(int, int)> func1;
    3. // 存储一个接受一个int参数并返回一个int的函数
    4. std::function<int(int)> func2;
    5. // 存储一个不接受任何参数的函数
    6. std::function<void()> func3;
    7. // 存储一个Lambda表达式
    8. std::function<int(int)> func4 = [](int x) { return x * 2; };

    在这些例子中,`func1`和`func2`可以用来存储任何接受相应参数类型的函数,`func3`可以用来存储任何不接受任何参数的函数,`func4`可以用来存储一个接受一个int参数并返回一个int的Lambda表达式。


     

    1. #include
    2. #include
    3. class A {
    4. public:
    5.     A(const std::function<void()>& f) :callback_(f) {};
    6.     void print() {
    7.         callback_();
    8.     }
    9. private:
    10.     std::function<void()> callback_;
    11. };
    12. int main() {
    13.     A obj([&]() {
    14.         std::cout << "Hello, World!" << std::endl;
    15.     });
    16.     obj.print();
    17.     return 0;
    18. }

    在这个例子中,我们定义了一个名为A的类,它有一个构造函数,接受一个名为callback_的std::function类型的参数。我们还定义了一个名为print的方法,用于调用callback_函数。在main函数中,我们创建了一个A类的对象,并将一个Lambda表达式作为其构造函数的参数传递。然后我们调用obj的print方法,输出"Hello, World!"

  • 相关阅读:
    java计算机毕业设计基于springboo个人家庭理财记账管理系统
    一个可见又不可见的窗口
    SpringMVC学习笔记
    7.从句学习
    nginx-module-vts监控nginx流量
    svnsync实现版本库的同步备份
    HTML+CSS+JS网页设计期末课程大作业 html+css+javascript+jquery化妆品电商网站4页面
    TELEC认证标准是什么?
    解决Microsoft已经阻止宏运行,因为此文件的来源不受信任。
    Python+ Flask轻松实现Mock Server
  • 原文地址:https://blog.csdn.net/m0_72703340/article/details/136401106