函数指针与回调
来源:互联网 发布: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++中应该是是一种函数指针的经典使用方法。在一开是接触回调是总是理解不了,现在回想起来当时的疑问主要有:
- 什么是回调函数?
- 回调函数的“回”字体现在哪?
- 什么时候应该使用回调函数?
本节就从这三个问题着手总结回调函数。
首先什么是回调函数?
答:回调函数是通过函数参数传递到其他代码(函数)的某一块代码的引用(函数地址),这使得底层的代码可以调用高层的子程序。如图所示:
回调函数的回体现在哪里?
答:如上图,回就体现在一开始是底层的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;}
运行结果如下:
由此,可以看出底层程序运行三次,调用了三次回调函数,回调函数又反过来调用了三次底层的变量。
什么时候应该使用回调函数?
答:以下是个人实际使用的总结:
①当高层某程序的运行取决于底层程序判断时可用。
②在两个层次之间传递值时可用,这个与观察者模式有点相似,高层(观察者)注册到底层(被观察者),底层(被观察者)根据运行逻辑通知或传递给高层(观察者)消息。所以可参考这个模式使用。
③根据函数指针的多态性,回调也可以实现多态。
- 函数指针和指针函数,函数指针与回调
- 函数指针与回调
- 函数指针与回调
- 函数指针与回调机制
- 函数指针与指针函数---应用为函数的回调
- c++虚函数的前奏--函数指针与回调
- 指针函数与函数指针
- 指针函数与函数指针
- 函数指针与指针函数
- 指针函数与函数指针
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针 与 指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 函数指针与指针函数
- 心路历路与团队奖惩 转
- Ubuntu 14.04下NFS安装配置
- 二维码
- [leetcode]330. Patching Array
- 完整的单步二维码扫描下载html代码包括微信
- 函数指针与回调
- 利用shell批量更改文件后缀名
- 第十章 内部类
- Linux shell的标准输入、输出和错误
- bzoj2938(ac自动机)
- 自编码神经网络
- Hadoop2.X 64位编译
- 杭电1014 ——Uniform Generator
- (转)对cloneable接口跟Object.clone方法的理解