[TOC]
函数指针
- 原理上来说,函数指针和变量的指针是一样的,都是指向内存中的某个地址;
一、函数指针的声明
C:
返回值类型 (*函数指针名称)(param 1, param 2, ...);
C++:
返回值类型 (类名::*函数指针名称)(param 1, param 2, ...);
二、函数指针的使用
- 函数指针作为形参和普通数据指针作为形参相同;
- 可以使用
typedef
简写:typedef int(*PFunction)(int);
,后面可以使用PFunction
声明函数指针;
(1)C语言
int (*pf)(int) = NULL;
函数指针的声明;int *pf(int);
缺了括号,就是返回值为int*
的函数;
int fun1(int temp)
{
return temp + 1;
}
int fun2(int temp)
{
return temp + 100;
}
void main()
{
int (*pf)(int) = NULL; //声明函数指针并初始化为空指针
//赋值和调用有两种方法
//法一
pf = fun1;
(*pf)(1); //2
//法二,建议使用,因为和变量指针使用方法相同
pf = &fun2;
pf(1); //101
}
(2)C++
- 全局函数可以使用C语言的写法;
- 只有public权限的函数才能使用函数指针;
- 使用类名控制的话,会限定函数指针,所以一般不使用,一般使用全局函数或者类的静态成员函数;
类成员写法示例如下:
class TestClass
{
public:
int Fun1(int temp){ return temp + 1; }
int Fun2(int temp) const{ return temp + 10; }
static int Fun3(int temp){ return temp + 100; }
};
//函数指针作为参数
void TestFun(int(*pf)(int), int temp){
cout<<pf(temp)<<endl;
}
void TestFun2(int(TestClass::*pf)(int), TestClass& a, int temp){
cout << (a.*pf)(temp) << endl;
}
void TestFun3(int(TestClass::*pf)(int) const, TestClass& a, int temp){
cout << (a.*pf)(temp) << endl;
}
//调用
void main()
{
//static
int(*pstaticf)(int) = NULL;
pstaticf = TestClass::Fun3;
cout << pstaticf(1) << endl; //101
TestFun(pstaticf, 1); //101
TestClass test_calss;
//normal function
int(TestClass::*pf)(int) = NULL;
pf = &TestClass::Fun1;
cout << (test_calss.*pf)(1) << endl; //2
TestFun2(pf, test_calss, 1); //2
//const
int(TestClass::*pConst)(int) const = NULL;
pConst = &TestClass::Fun2;
cout << (test_calss.*pConst)(1) << endl; //11
TestFun3(pConst, test_calss, 1); //11
}
三、函数指针作为函数参数
typedef int(*PFunction)(int);
//法一:
PFunction TestFunction(); //可读性强,建议使用
//法二
int(*TestFunction(float))(int); //读起来复杂
法二说明:
TestFunction
有形参列表,说明其是一个函数;TestFunction(float)
说明该函数形参为float
类型;TestFunction
前面有*
,说明该函数返回一个指针类型;- 最后有
(int)
说明,返回的指针是函数指针,该函数指针有形参,为int
形;
回调函数
回调函数就是利用函数指针进行函数的反向调用。
例如:在类A内创建类B的对象,类A调用B的接口,完成一系列动作,并希望在动作的个别节点上通知类A执行状态。类A调用B的接口,很简答,使用B的指针进行普通函数调用即可,但是B如何通知A呢,B的内部又没有A的指针,就需要回调函数,类A将回调函数传给B,B在需要的时候调用回调函数即可。
示例1:
typedef void(*CallFuncation)(int a);
class MyCallBack
{
public:
MyCallBack() :callbackFunction(NULL), a(0){}
void SetCallback(CallFuncation callback_function){
callbackFunction = callback_function;
callbackData = p_callback_data;
}
void Run(){
a = 999;
if (callbackFunction != NULL){
callbackFunction(a, callbackData);
}
}
private:
CallFuncation callbackFunction;
int a;
};
void myFun(int temp)
{
cout << temp << endl;
}
int _tmain()
{
MyCallBack my_callback;
my_callback.SetCallback(myFun);
return 0;
}
这样,MyCallBack在运行过程中将自身的属性传回给了调用者,但是,调用者若使用动态传递参数呢?上例中,需要在输出的结果长加上某个值,或其他参数呢?示例如下:
typedef void(*CallFuncation)(int a, const void* pCallback);
class MyCallBack
{
public:
MyCallBack() :callbackFunction(NULL), a(999){}
void SetCallback(CallFuncation callback_function, const void* p_callback_data = NULL){
callbackFunction = callback_function;
callbackData = p_callback_data;
}
void Run(){
if (callbackFunction != NULL){
callbackFunction(a, callbackData);
}
}
private:
CallFuncation callbackFunction;
const void* callbackData;
int a;
};
void myFun(int temp, const void* pCallback)
{
cout << temp << " " << *(int*)(pCallback) << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
int my_param = 888;
MyCallBack my_callback;
my_callback.SetCallback(myFun, &my_param);
my_param = 999;
my_callback.Run();
int aaa = 123456;
my_callback.SetCallback(myFun, &aaa);
my_callback.Run();
return 0;
}
在设置回调函数的时候,加上一个传递参数的指针,并保存起来,在调用回调函数的时候,再传回去即可。
这里只用const void 表示,不能在内部使用该指针改变任何内容,该指针只作为参数传递使用。