C++学习:回调函数(callback)

简介:

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
可能这些概念性的东西不是太好理解,通俗一点,回调函数就是在两个独立函数或者独立类通信的通道

举个例子:

财务处是负责对公司财务状况和每个月的开销进行汇总,老板只会去看每个月的报表。

那么在这个当中,老板不会去关心,财务整个汇总的过程,他只会去关心结果,那么,如果从面向对象的方法去理解的话,老板是一个对象.财务部是一个对象,当老板想看报表的时候,会跟财务打个招呼,等财务部汇总完了.然后将报表再去提交给老板,那么问题来了,而两个类之间实现通信的就是接口回调,从财务类的中,将结果回调到对象中.这种实现是通过接口自动完成的。
 
如果用C语言的面向过程去理解的话,那么老板想看报表可以理解为一个函数,而财务处计算过程可以看成一个函数,如果老板想看报表的话,可以直接通过调用财务处函数的返回结果来查看.这中主要是依赖于函数指针的形式来实现。

基于C语言的回调函数来实现一个回调的过程

/**
* Filename:  callback.c
*/
#include<stdio.h>
#include<stdlib.h>

/* *
 *财务的统计状况函数
 */
static int finance_result(int *a,int n);

/**
 *老板想看财务报表
 */
void boss_read_finance(int *array,int n,int (*fp)(int*,int));

int main(int argc,char* argv[]){
  //定义一个数组数据
  int array[10] = {1,2,3,4,5,6,7,8,9,10};
  //因为C语言中函数名也是地址,因此对于形参数是函数指针的话,这个时候直接将地址传进去就可以了;
  //注意:函数指针是指向函数的地址,对于fp是地址,那么调用的时候固然需要(*fp)
  //也可以这样写:
  //int (*fp)(int *a,int n);
  //fp = finance_result;
  //boss_read_finance(array,10,finance_result);

  boss_read_finance(array,10,finance_result);

  return 0;
}

/**
 *老板查看财务状况的实现,参数中有一个函数指针,
 */
void boss_read_finance(int* array,int n,int (*fp)(int* a,int n)){
  //对于老板来说,他是不需要去了解财务部的具体实现的过程,只要结果就行了
  //这就有助于我们对函数封装
  int result = (*fp)(array,n);
  printf("caculate result:%d\n",result);
}

/**
 *财务计算报表的具体实现
 */
static int finance_result(int* a,int n){
  int result = 0;
  int i =  0;
  for(i = 0;i < n; i++){
    result += *(a+i);
  }
  return result;
}

基于C++面向对象过程的代码

/**
* Finance.h
*/
#ifndef TEST1_FINANCE_H
#define TEST1_FINANCE_H

#include <iostream>
using namespace std;

class CallBack {
 public:
  virtual void setFinanceResult(int result) const = 0;
};

class Finance {
 public:
  Finance(CallBack* mCallBack2) : mCallBack(mCallBack2) {
    cout << "finance constructor" << endl;
  }

  ~Finance() {
    cout << "finance destructor" << endl;
  }

  void caculateFinance(int *a, int n) {
    int result = 0;
    for (int i = 0; i < n; ++i) {
      result += *(a + i);
    }
    if (nullptr != mCallBack) {
      cout << "result: " << result << endl;
      mCallBack->setFinanceResult(result);
    }
  }

 private:
  CallBack* mCallBack;
};

class Boss : public CallBack {
 public:
  Boss() {
    mFinance = new Finance(this);
    cout << "boss contructor" << endl;
  }

  ~Boss() {
    delete mFinance;
    cout << "boss destructor" << endl;
  }

  void readFianance(int *array, int n) {
    cout <<"boss readFianance" << endl;
    mFinance->caculateFinance(array, n);
  }

  void setFinanceResult(int result) const {
    cout << "caculate result: " << result << endl;
  }

 private:
  Finance* mFinance;
};

#endif //TEST1_FINANCE_H
/**
*Finance.cpp
*/
#include "Finance.h"
int main() {
  int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  Boss boss;
  boss.readFianance(array, 10);
  return 0;
}

其实这个案例能够让我们对回调有更加深刻的认识:
1:老板想查看财务(调用自己函数,函数在boss内)
2:通知财务,我要查看报表(进行计算的过程,函数在finance内部)
3:财务算好之后,返回给老板(回调的函数在boss内部)
也就是回调就是把不需要自己处理的东西放到别的类去,然后等其处理完毕之后,再返回给调用的类.

总结:

回调四步曲:

  1. 定义一个回调接口
  2. 调用类去实现这个接口,重写方法
  3. 被调用者将接口做为参数传递进去,并且在某个时刻进行出发
  4. 调用者在调用的时候去实例化这个回调接口(如上述案例中因为已经实现了接口,所以将类本身对应的对象作为参数传递进去)

转载自:https://blog.csdn.net/qq_29924041/article/details/74857469

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值