转自【 http://hipercomer.blog.51cto.com/4415661/792300 】,有删改
======================
CONTENTS
2 函数指针简单介绍
2.1 什么是函数指针
函数指针是一个指向函数的指针,函数指针表示一个函数的入口地址。使用函数指针的好处就是在处理“在运行时根据数据的具体状态来选择相应的处理方式”这种需求时更加灵活。
简单的例子:
float minus(float a,float b){return a-b;} typedef float (*pf)(float,float); 。。。。。 。。。。。 void switch_fp_impl(float a,float b,pf p) { float result=0.0; result=p(a,b); } int main() { int i=0; for(i=0;i<N;i++) { switch_fp_impl(12.32,54.14,minus); } return 0; }
3 C/C++函数指针的语法
从语法上讲,有两种不兼容的函数指针形式:
(1) 指向C语言函数和C++静态成员函数的函数指针
(2) 指向C++非静态成员函数的函数指针
不兼容的原因是因为在使用C++非静态成员函数的函数指针时,需要一个指向类的实例的this指针,而前一类不需要。
3.1 定义一个函数指针
指针是变量,所以函数指针也是变量,因此可以使用变量定义的方式来定义函数指针,对于普通的指针,可以这么定义:
int a=10;
int *pa=&a;
这里,pa是一个指向整型的指针,定义这个指针的形式为:
int * pa;
区别于定义非指针的普通变量的“形式”就是在类型中间和指针名称中间加了一个“*”,所以能够表达不同的“内容”。这种形式对于表达的内容是完备的,因为它说明了两点:(1)这是一个指针(2)这是一个指向整型变量的指针
以下给出三个函数指针定义的形式,第一个是C语言的函数指针,第二个和第三个是C++的函数指针的定义形式(都是指向非静态函数成员的函数指针):
int (*pFunction)(float,char,char)=NULL;
int (MyClass::*pMemberFunction)(float,char,char)=NULL;
int (MyClass::*pConstMemberFunction)(float,char,char) const=NULL;
3.3 给函数指针赋值和调用
给函数指针赋值,就是为函数指针指定一个函数名称。这个过程很简单,下面是两个例子:
int func1(float f,int a,int b){return f*a/b;}
int func2(float f,int a,int b){return f*a*b}
然后我们给函数指针pFunction赋值:
pFunction=func1;
pFunction=&func2;
上面这段代码说明了两个问题:(1)一个函数指针可以多次赋值(想想C++中的引用)(2)取地址符号是可选的,却是推荐使用的。
最后我们来使用这个函数:
pFunction(10.0,’a’,’b’);
(*pFunction)(10.0,’a’,’b’);
在C++中,对于赋值,你必须要加“&”,而且你还必须再次之前已经定义好了一个类实例,取地址符号要操作于这个类实例的对应的函数成员上。在使用成员函数的指针调用成员函数时,你必须要加类实例的名称,然后再使用.*或者->*来使用成员函数指针。举例如下:
MyClass { public: int func1(float f,char a,char b) { return f*a*b; } int func2(float f,char a,char b) const { return f*a/b; } }
首先来赋值:
MyClass mc;
pMemberFunction= &mc.func1; //必须要加取地址符号
pConstMemberFunction = &mc.func2;
接下来,调用函数:
(mc.*pMemberFunction)(10.0,’a’,’b’);
(mc.*pConstMemberFunction)(10.0,’a’,’b’);
例子:
#include<stdio.h> float func1(float f,char a,char b) { printf("func1\n"); return f*a/b; } float func2(float f,char a,char b) { printf("func2\n"); return f*a*b; } class MyClass { public: MyClass(float f) { factor=f; } float func1(float f,char a,char b) { printf("MyClass::func1\n"); return f*a/b*factor; } float func2(float f,char a,char b) const { printf("MyClass::func2\n"); return f*a*b*factor; } private: float factor; }; int main(int argc,char *argv[]) { float (*pFunction)(float,char,char)=NULL; float (MyClass::*pMemberFunction)(float,char,char)=NULL; float (MyClass::*pConstMemberFunction)(float,char,char)const=NULL; float f=10.0; char a='a',b='b'; float result; pFunction=func1; printf("pointer pFunction's address is:%x\n",pFunction); result=(*pFunction)(f,a,b); printf("result=%f\n",result); pFunction=&func2; printf("pointer pFunction's address is:%x\n",pFunction); result=pFunction(f,a,b); printf("result=%f\n",result); if(func1!=pFunction) printf("not equal.\n"); pMemberFunction=&MyClass::func1; MyClass mc1(0.2); printf("pointer pMemberFunction's address is:%x\n",pMemberFunction); result=(mc1.*pMemberFunction)(f,a,b); printf("result=%f\n",result); pConstMemberFunction=&MyClass::func2; MyClass mc2(2); printf("pointer pConstMemberFunction's address is:%x\n",pConstMemberFunction); result=(mc2.*pConstMemberFunction)(f,a,b); printf("result=%f\n",result); return 0; }
使用类的静态函数成员的函数指针和使用C语言的函数很类似,这里仅仅给出一个例子和其执行结果:
程序代码为:
#include<iostream> class MyClass { public: static float plus(float a,float b) { return a+b; } }; int main() { float result,a=10.0,b=10.0; float (*p)(float,float); p=&MyClass::plus; result=p(a,b); printf("result=%f\n",result); return 0; }
3.4 函数指针作为参数
例子:
#include<stdio.h> float add(float a,float b){return a+b;} float minus(float a,float b){return a-b;} int pass_func_pointer(float (*pFunction)(float a,float b)) { float result=pFunction(10.0,12.0); printf("result=%f\n",result); } int main() { pass_func_pointer(add); pass_func_pointer(minus); return 0; }
3.5 使用函数指针作为返回值
所以对于以下形式:
float (* func(char op) ) (float ,float)
其具体含义就是,声明了这样一个函数:
l 其名称为func,其参数的个数为1个;
l 其各个参数的类型为:op—char;
l 其返回变量(函数指针)类型为:float(*)(float,float)
再次强调:函数指针时变量哦。
到了这里之后,我们再来分析一下unix的系统调用函数signal的定义形式:
void (*signal)(int signo,void (*func)(int)))(int);
其具体含义为就是,声明了这样一个函数:
l 其函数名称为:signal
l 其参数个数为:2
l 其各个参数的类型为:signo–int, func— void (*)(int)
l 其返回的变量(函数指针)的类型为:void(*)(int)
上面这个函数比较经典,有一个参数类型为函数指针,返回值还是函数指针。
例子:
float add(float a,float b){return a+b;} float minus(float a,float b){return a-b;} float(* FunctionMap(char op) )(float,float) { switch(op) { case '+': return add; break; case '-': return minus; break; default: exit(1); } } int main() { float a=10,b=5; char ops[]={'+','-'}; int len=strlen(ops); int i=0; float (*returned_function_pointer)(float,float); for(i=0;i<len;i++) { returned_function_pointer=FunctionMap(ops[i]); printf("%c %f\n",ops[i],returned_function_pointer(a,b)); } return 0; }
3.6 使用函数指针数组
现在我们来类比函数指针数组的定义,定义一个指向函数指针类型为:float (*)(float,float)的函数指针数组,数组长度为10.正确的形式为:
float(* pFunctionArray[10])(float,float)
下面是一个例子程序:
float add(float a,float b){return a+b;} float minus(float a,float b){return a-b;} float multiply(float a,float b){return a*b;} float divide(float a,float b){return a/b;} int main() { float(*func_pointers[4])(float,float)={add,minus,multiply,divide}; int i=0; float a=10.0,b=5.0; for(i=0;i<4;i++) { printf("result is %f\n",func_pointers[i](a,b)); } return 0; }
3.7 使用typedef
现在我们要将float (*)(float,float)类型声明为一种新类型:
typedef float(*fpType)(float,float);
这样我们就可以用fpType来表示float (*)(float,float)这种类型了。所以定义一个新的指向float (*)(float,float)类型的指针变量的时候,我们就可以采用下面这种形式了:
fpType pFunction;
在定义函数指针数组的时候可以这样定义:
fpType pFunctions[10];
在定义函数指针类型参数时可以这样定义:
void func(fpType pFunction);
在定义函数指针类型的返回值时可以这样定义:
fpType func(int a);
现在我们再来看一下,unix中的那个signal函数,其形式为:
void (*signal)(int signo,void (*func)(int)))(int);
现在我们定义一个类型为:
typedef void (*pSgnType)(int);
这样上面的函数就能表达为:
pSgnType signal(int signo,pSgnType func);
这样是不是看起来清爽多了。
其实上面的signal函数也能这样定义:
首先引入新类型:
typedef void SgnType(int)
然后signal函数的声明改为:
SgnType *signal(int signo,SgnType *func);
发表评论