编程|理解回调函数是caller和callee之外的第三者(callbackee)

(36) 2023-10-01 16:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说编程|理解回调函数是caller和callee之外的第三者(callbackee),希望能够帮助你!!!。

我们知道,函数是一个功能模块的封装,是算法的具体实现,是高级编程语言中最重要的概念之一。

函数需要被调用才可以发挥作用,不然只是个摆设。

调用时,自然就有了两个主体:

调用函数(caller)→ 被调函数(callee)。

我们知道,函数的参数是函数调用时,被调用函数与调用函数之间重要的沟通渠道,函数的适当设置,可以让被调用函数更灵活,通性性更强,被重用的机会越大。

假设要编写一个排序函数,你可能会编写一个降序函数,也可能编写一个升序函数。而两个函数仅有一行代码的区别,且C、C++是不允许内嵌函数定义的。如果将两个函数整合到一起呢?函数指针做函数参数便闪亮登场了。
函数指针做callee函数的参数,在callee函数中使用这个函数指针变量,而不是将升序或降序的逻辑写死在callee的函数体内。由这个函数指针变量再去调另一个函数(也就是所说的第三者)定义的升序或降序逻辑。这样的由被调函数callee再去调用一个第三者函数(回调函数,可以新建一个英文词callbakcee,)的过程称为回调(callback)。

这样就有了两个调用过程,三个主体

caller call callee callback callbackee

都有一个调字,在英文中就是call。

// 7-16 通用的冒泡排序函数的应用
#include <iostream>
#include <cstring>
using namespace std;

template <class T>
void sort(T a[], int size, bool (*f)(T,T));                     // callee
bool increaseInt(int x, int y)  {return x<y;}                   // callbackee1
bool decreaseInt(int x, int y) {return y<x;}                    // callbackee2
bool increaseString(char *x, char *y)  {return strcmp(x,y)<0;}  // callbackee3
bool decreaseString(char *x, char *y)  {return strcmp(x,y)>0;}  // callbackee4 

int main()                                                      // caller
{
    int a[] = {3,1,4,2,5,8,6,7,0,9}, i;
    char *b[]= {"aaa","bbb","fff","ttt","hhh","ddd","ggg","www","rrr","vvv"};
    
    sort(a, 10,increaseInt );
    for (i = 0; i < 10; ++i) cout << a[i] <<"\t";
    cout << endl;
    
    sort(a, 10,  decreaseInt);
    for ( i = 0; i < 10; ++i) cout << a[i] <<"\t";
    cout << endl;  
    
    sort(b, 10, increaseString );
    for (i = 0; i < 10; ++i) cout << b[i] <<"\t";
    cout << endl;
    
    sort(b, 10,  decreaseString);
    for ( i = 0; i < 10; ++i) cout << b[i] <<"\t";
    cout << endl;  
    while(1);
    return 0;
}

// 通用的冒泡排序函数
template <class T>
void sort(T a[], int size, bool (*f)(T,T))
{
    bool flag;
    int i, j;
    
    for (i = 1; i < size; ++i) {
        flag = false;
        for (j = 0; j <size - i; ++j)	{
            if (f(a[j+1], a[j]))  {
                T tmp = a[j];
                a[j] = a[j+1];
                a[j+1] = tmp;
                flag = true;
            }
        }
        if (!flag) break;	
    }
}
/*
0       1       2       3       4       5       6       7       8       9
9       8       7       6       5       4       3       2       1       0
aaa     bbb     ddd     fff     ggg     hhh     rrr     ttt     vvv     www
www     vvv     ttt     rrr     hhh     ggg     fff     ddd     bbb     aaa
*/

回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。同时,有一些需求必须要使用回调函数来实现。

C语言的回调函数只能通过函数指针实现,在C++中则可以使用匿名函数(lambda)或仿函数(functor)作为回调函数。

// 7-19 lambda函数作为通用的冒泡排序函数的参数
#include <iostream>
#include <cstring>
using namespace std;

template <class T>
void sort(T a[], int size, bool (*f)(T,T));                     // callee

int main()                                                      // caller
{
    int a[] = {3,1,4,2,5,8,6,7,0,9}, i;
    char *b[]= {"aaa","bbb","fff","ttt","hhh","ddd","ggg","www","rrr","vvv"};
    
    sort<int>(a,10,[](int x, int y)->bool {return x<y; });
    for (i = 0; i < 10; ++i) cout << a[i] <<"\t";
    cout << endl;
    
    sort<int>(a,10,[](int x, int y)->bool {return x>y; });
    for ( i = 0; i < 10; ++i) cout << a[i] <<"\t";
    cout << endl;  
    
    sort<char*>(b,10,[](char *x, char *y)->bool {return strcmp(x,y) < 0; });
    for (i = 0; i < 10; ++i) cout << b[i] <<"\t";
    cout << endl;
    
    sort<char*>(b,10,[](char *x, char *y)->bool {return strcmp(x,y) > 0; });
    for ( i = 0; i < 10; ++i) cout << b[i] <<"\t";
    cout << endl;     
  
    while(1);
    return 0;
}

// 通用的冒泡排序函数
template <class T>
void sort(T a[], int size, bool (*f)(T,T))
{
    bool flag;
    int i, j;
    
    for (i = 1; i < size; ++i) {
        flag = false;
        for (j = 0; j <size - i; ++j)	{
            if (f(a[j+1], a[j]))  {
                T tmp = a[j];
                a[j] = a[j+1];
                a[j+1] = tmp;
                flag = true;
            }
        }
        if (!flag) break;	
    }
}
/*
0       1       2       3       4       5       6       7       8       9
9       8       7       6       5       4       3       2       1       0
aaa     bbb     ddd     fff     ggg     hhh     rrr     ttt     vvv     www
www     vvv     ttt     rrr     hhh     ggg     fff     ddd     bbb     aaa
*/

ref

C++|辨析函数指针、函数对象、Lambda表达式及后者最优的原因

-End-

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复