函数指针与回调

在上篇文章总结了指针的一些用法,本节则总结了指向函数的一种指针-函数指针的概念与用法。前一段时间做项目的时候遇到了函数指针以及回调,因为之前一直在使用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;
}

 运行结果如下: 


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

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

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

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

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值