回调函数

搞好了好久想重新复习一遍C/C++ 不知道 怎么复习 干脆就慢慢把一些知识点放到这边就当复习了也是边看别人博客边写

什么是回调函数:

在我的理解当中只要是把函数作为参数输入的函数就是回调函数。

官方:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

如何定义回调函数

要实现回调函数,最关键的一点就是要将函数的指针传递给一个函数,然后这个函数就可以通过这个指针来调用回调函数了。注意,回调函数并不是C语言特有的,几乎任何语言都有回调函数。在C语言中,我们通过使用函数指针来实现回调函数。那函数指针是什么?

函数指针和指针函数

1、指针函数是指带指针的函数,即本质是一个函数,函数返回类型是某一类型的指针。

类型标识符 *函数名(参数表)

int *f(x,y);

首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

int * GetDate(int wk,int dy);
main()
{
  int wk,dy;
  do{
  printf(Enter week(1-5)day(1-7)\n);
  scanf(%d%d,&wk,&dy);
  }
  while(wk<1||wk>5||dy<1||dy>7);
  printf(%d\n,*GetDate(wk,dy));
}

int * GetDate(int wk,int dy)
{
  static int calendar[5][7]=
  {
    {1,2,3,4,5,6,7},
    {8,9,10,11,12,13,14},
    {15,16,17,18,19,20,21},
    {22,23,24,25,26,27,28},
    {29,30,31,-1}
  };
  return &calendar[wk-1][dy-1];
}
//返回calendar数组中某个值的地址  主函数通过指针*{地址}获取值
2、函数指针是指向函数的指针变量,即本质是一个指针变量。
定义一个函数指针
typedef void (*name)(int, int, float);
函数指针,顾名思义,它指向一个函数的入口地址,其定义及使用如下:
returntype(*ptr)(typename variable,…)
返回类型指针名称指向函数的参数表

你定义了函数:

int cal(int a,int b)   
int get(int a,int b)

定义函数指针:

int (*ptr)(int ,int); 
第二种:
typedef void (*tp_func)(int, int, float);
tp_func ptr = NULL;

初始化:

 int (*ptr)(int ,int)=cal;
 int (*ptr)(int,int)=&cal; 将ptr赋值为cal函数,这两种是等价的。

调用:

 int val1=3,val2=4;
 ptr(val1,val2);
 (*ptr)(val1,val2);    这两种调用方式也是完全等价的。

函数指针作为参数传给函数

/* func3 将函数指针 p_func 作为其形参 */
func3就是一个回调函数其中参数 void (*p_func)(int, int, float) 是一个函数指针

void func3(int a, int b, float c, void (*p_func)(int, int, float))
{
    (*p_func)(a, b, c);
}

/* func4 调用函数func3 */
void func4()
{
    func3(1, 2, 3.0, func_1);
    /* 或者 func3(1, 2, 3.0, &func_1); */
}

函数指针作为函数返回类型
有了上面的基础,要写出返回类型为函数指针的函数应该不难了,下面这个例子就是返回类型为函数指针的函数:

void (* func5(int, int, float ))(int, int)
{
    ...
}

在这里, func5 以 (int, int, float) 为参数,其返回类型为 void (*)(int, int) 。

函数指针数组

在开始讲解回调函数前,最后介绍一下函数指针数组。既然函数指针也是指针,那我们就可以用数组来存放函数指针。下面我们看一个函数指针数组的例子:

/* 方法1 */
void (*func_array_1[5])(int, int, float);

/* 方法2 */
typedef void (*p_func_array)(int, int, float);
p_func_array func_array_2[5];

上面两种方法都可以用来定义函数指针数组,它们定义了一个元素个数为5,类型是 void (*)(int, int, float) 的函数指针数组。

回调函数案例

下面是一个四则运算的简单回调函数例子:
第一步
要完成加减乘除,我们需要定义四个函数分别实现加减乘除的运算功能,这几个函数就是:

  • 加减乘除函数

    float ADD(float a, float b) 
     {
         return a + b;
     }
     
     float SUB(float a, float b) 
     {
         return a - b;
     }
     
     float MUL(float a, float b) 
     {
         return a * b;
     }
     
     float DIV(float a, float b) 
     {
         return a / b;
     }
    

第二步
定义四个函数指针分别指向这四个函数:

  • 函数指针结构体
    typedef struct _OP {
        float (*p_add)(float, float); 
        float (*p_sub)(float, float); 
        float (*p_mul)(float, float); 
        float (*p_div)(float, float); 
    } OP; 
  • 初始化函数指针
void init_op(OP *op)
{
    op->p_add = ADD;
    op->p_sub = SUB;
    op->p_mul = &MUL;
    op->p_div = &DIV;
}

第三步
我们需要创建一个“库函数”,这个函数以函数指针为参数,通过它来调用不同的函数:

  • 库函数
    float add_sub_mul_div(float a, float b, float (*op_func)(float, float))
    {
        return (*op_func)(a, b);
    }

第四步
当这几部都完成后,我们就可以开始调用回调函数了:

/* 调用回调函数 */ 
printf("ADD = %f, SUB = %f, MUL = %f, DIV = %f\n", 
        add_sub_mul_div(1.3, 2.2, op->p_add), 
        add_sub_mul_div(1.3, 2.2, op->p_sub), 
        add_sub_mul_div(1.3, 2.2, MUL), 
        add_sub_mul_div(1.3, 2.2, DIV));

简单的四部便可以实现回调函数。在这四步中,我们甚至可以省略第二步,直接将函数名传入“库函数”,比如上面的乘法和除法运算。回调函数的核心就是函数指针

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值