函数指针与回调

来源:互联网 发布:linux上传文件命令 编辑:程序博客网 时间:2024/06/12 01:13

在上篇文章总结了指针的一些用法,本节则总结了指向函数的一种指针-函数指针的概念与用法。前一段时间做项目的时候遇到了函数指针以及回调,因为之前一直在使用java语言开发,所以对此感觉很纠结。虽然对函数指针有了解,对这个函数指针与回调的使用非常疑惑,于是再次翻阅了c++ primer以及查阅了回调函数的相关含义。下面是一些总结:

1.函数指针概念

在c++ primer中对函数指针的一些解释:

①函数与数组等数据项一样存在地址。函数地址是存储其机器语言代码的内存的开始地址。

②与数组首地址一样,函数的函数名表示该函数的入口地址,即函数地址。

③声明一个函数指针必须指定指针指向的函数类型。函数类型则由函数的返回类型以及函数的特征表(参数列表)表示。声明的格式是:

type   (*ptrName) (type,type);

例如:

int (*ptrF)(int,int);

2.函数指针的使用

根据上述定义,可以知道只要符合函数类型的函数均可以赋值给相应的函数指针。从这个角度看,一个函数指针可以表示多个函数,这也是一种多态的体现。函数指针的使用如下:

typedef int (*Pfunc)(int,int);//定义一个类型为函数指针int (*r_Pfunc(char op))(int,int);//声明一个返回函数指针的函数,返回函数指针类型为int(int,int)*,函数为s_Pfunc(char op)int Pfunc1(int a,int b);int Pfunc2(int a,int b);int Pfunc3(int a,int b);Pfunc returnPFunc(); int main(){using namespace std;          Pfunc pfunc;pfunc=Pfunc1;pfunc(1,2);pfunc=Pfunc2;pfunc(3,4);pfunc = returnPFunc();pfunc(5,6);        system("pause");return 0;}int Pfunc1(int a,int b){cout<<"Pfunc1打印值a="<<a;cout<<";Pfunc1打印值b="<<b<<"\n";return 0;}int Pfunc2(int a,int b){cout<<"Pfunc2打印值a="<<a;cout<<";Pfunc2打印值b="<<b<<"\n";return 0;}int Pfunc3(int a,int b){cout<<"Pfunc3打印值a="<<a;cout<<";Pfunc3打印值b="<<b<<"\n";return 0;}Pfunc returnPFunc(){return Pfunc3;}
运行结果如下:


根据以上结果可以看出:只要函数指针与某函数的函数类型符合,均可将函数地址赋值给函数指针,进而直接使用函数指针。图示三个函数分别赋值给函数指针,而后调用该函数指针,得出对应函数的执行结果,体现出函数指针的多态性。

在上述实例中,可以看到还有一个关键字的用法:typedef。在这里主要总结了三种用法:

①如上使用typedef定义函数指针复杂的结果为一个函数类型,程序编写可直接使用该函数类型。

②使用typedefy定义结构体。如程序所示

typedef struct s_Strct{int s1;double s2;char s3;} typeStruct,*ptypeStruct; <pre name="code" class="cpp">//声明一个结构体,对结构体进行自定义类型,其中typeStruct和s_Strct都可以作为类型使用,ptypeStruct是指向该结构体的指针,也可以作为类型使用
typeStruct s_Test={1,1.2,'#'}; //使用typedefine定义的struct的类型 ptypeStruct s_p=new typeStruct; //使用typedefine定义的struct类型指针s_Strct s_ss = { 0,1.1,'&'}; //使用struct名称类型

③使用typedef定义基本类型。具体如下:

//给int类型重新定义一个新类型,以后的int均可被word替换使用typedef int word;word w_Value = 30;

3.回调概念与使用

回调函数在c++中应该是是一种函数指针的经典使用方法。在一开是接触回调是总是理解不了,现在回想起来当时的疑问主要有:

  1. 什么是回调函数?
  2. 回调函数的“回”字体现在哪?
  3. 什么时候应该使用回调函数?

本节就从这三个问题着手总结回调函数。

首先什么是回调函数?

答:回调函数是通过函数参数传递到其他代码(函数)的某一块代码的引用(函数地址),这使得底层的代码可以调用高层的子程序。如图所示:


回调函数的回体现在哪里?

答:如上图,回就体现在一开始是底层的testB方法调用高层的testA方法,结果testA方法反过来调用了底层程序中的变量,并回传给高层程序中的变量。所以说回就体现在callback函数调用了调用callback所在层次的变量这一环节上。

那么,根据上面的图示解释,应该已经有了一点概念,现在我们直接将上面的图示用程序运行一下:首先建立两个类:

AB.h文件:

#pragma once#include <iostream>using namespace std;typedef void ( *CallBack)(int,int);class A{public:A();~A(void);static void testA(int a,int b);void showaValue();static int aValue;};class B{private:int bValue;int cValue;public:B(int bvalue,int cvalue);~B(void);void testB(CallBack callback);};

AB.cpp文件:

#include "AB.h"int A::aValue =0;A::A(){}A::~A(void){}void A::testA(int a,int b){cout<<"执行高层回调函数..."<<"\n";A::aValue += a+b;}void A::showaValue(){cout<<"A.aValue的值="<<A::aValue<<"\n\n";}B::B(int bvalue,int cvalue){bValue = bvalue;cValue = cvalue;}B::~B(void){}void B::testB(CallBack callback){cout<<"执行底层方法..."<<"\n";callback(bValue,cValue);}

主程序:

<p>       </p><pre name="code" class="cpp">int main(){         A* aclass = new A; B* bclass = new B(1,2); aclass->showaValue(); for (int i=0;i<3;i++) { cout<<"第"<<i+1<<"次执行底层"<<"\n"; bclass->testB(A::testA); aclass->showaValue(); }    system("pause");    return 0;}

运行结果如下:


    由此,可以看出底层程序运行三次,调用了三次回调函数,回调函数又反过来调用了三次底层的变量。

什么时候应该使用回调函数?

答:以下是个人实际使用的总结:

①当高层某程序的运行取决于底层程序判断时可用。

②在两个层次之间传递值时可用,这个与观察者模式有点相似,高层(观察者)注册到底层(被观察者),底层(被观察者)根据运行逻辑通知或传递给高层(观察者)消息。所以可参考这个模式使用。

③根据函数指针的多态性,回调也可以实现多态。


0 0
原创粉丝点击