一:起因
(1)指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针,即我们常见的函数类型,且返回值是指针。
(2)函数指针是指向函数的指针变量,即本质是一个指针变量,是一个指向函数(可能是代码区)的首地址的指针,正如我们都知道,数组名就是指向数组第一个元素的常量指针(详见《数组拾遗》)。同理,对于一个函数而言,函数名也是指向函数第一条指令的常量指针。而编译器要做的就是在程序编译之后,为每个函数分配一个首地址,即该函数第一条指令的地址。一般情况下,我们可以用一个指针来保存这个地址,而这个指针就是函数指针,该指针可以看作是它指向函数的别名,所以我们可以用该指针来调用这个函数。
(3)对指针的应用是C语言编程的精髓所在,而回调函数就是C语言里面对函数指针的高级应用。简而言之,回调函数是一个通过函数指针调用的函数。如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。
(4)我们非常熟悉的,而且经常用到的可能就是sort(begin,end)函数和 sort(begin,end,cmp);其中cmp正事函数名(即像数组名一样代表函数的首地址):
bool cmp(void const *a,void const *b)
{
return *((int *)a) > *((int *)b);
}
注意强制类型转换,比较函数的参数必须被声明为void *以匹配查找函数的原型,然后强制转换为(int *)类型用于比较整型。然后把一个指向这个函数的指针作为参数传递给查找函数,查找函数调用这个比较函数来执行比较,采用这个方法,任何类型的值得都可以进行比较。
(5)注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
二:详细分析
(1)指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针
类型标识符 *函数名(参数表)
int *f(x,y);
首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。例如:
float *fun();
float *p;
p = fun(a);
(2)函数指针是指向函数的指针变量,即本质是一个指针变量。
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。例如:
void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
fptr=&Function;
fptr=Function; // 建议用这种方式
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();// 建议用这种方式
(3)易混淆的地方:
函数指针的定义:
type (*func)(type&,type &) 或者 type (*func)(type ,type)
该语句声明了一个指针func,它指向了一个函数,这个函数带有了2个type型参数并返回一个type的值。(p.s. type类型可以被看成是int或者是floast等C++的类型)。
A:一个指向函数的指针必须确保该函数被定义且分配了内存,否则它将指向一个空地址,这个可是大忌!
B: 特别注意第一个括号的位置。如果我们不写括号,如下:
type *func(type ,type)
这就不是一个指向函数的指针了,而是声明了一个函数,该函数返回一个type类型的指针
有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的.函数指针有两个用途:调用函数和做函数的参数。
( 4 ) 注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针 * 号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。三:函数指针的高级应用---- 作为函数的参数
(1)下面程序中,给出了三种不同类型的函数指针,分别用(1)(2)(3)做了标注区分;分为声明部分,实现部分,调用部分。
(2)代码
#include
using namespace std;
void my_swap(int &,int &);// (4)普通函数的声明
int my_min(int,int);// (5)普通函数的声明
void my_input(void (*func)(int &,int &));//(1) 带有函数指针参数的声明
void my_input(int (*func)(int,int));// (2)带有函数指针参数的声明
void my_print(int,int,int (*func)(int,int));// (3)带有函数指针参数的声明
int main()
{
cout << "please input two numbers:" << endl;
my_input(my_swap);//(1) 带有函数指针参数的调用,函数名即为函数代码区的首地址
my_input(my_min);// (2)带有函数指针参数的调用,函数名即为函数代码区的首地址
int a,b;
cin >> a >> b;
my_print(a,b,my_min);// (3)带有函数指针参数的调用,函数名即为函数代码区的首地址
return 0;
}
void my_input(void (*func)(int &,int&))// (1)带有函数指针参数的实现
{
int a,b;
cin >> a >> b;
func(a,b);// 指针指向的函数代码区的首地址
cout << a << ",,," << b << endl;
}
void my_input(int (*func)(int,int))// (2)带有函数指针参数的实现
{
int a,b;
cin >> a >> b;
int mi = func(a,b);// 指针指向的函数代码区的首地址
cout << "a,,,b:" << mi << endl;
}
void my_print(int a,int b,int (*func)(int,int))// (3)带有函数指针参数的实现
{
int mi = func(a,b);// 指针指向的函数代码区的首地址
cout << a << ",," << b << ",," << mi << endl;
}
int my_min(int a,int b)// (5)
{
return a