函数指针就像是一个指针是该变量地址类似,只不过指向的变量变为指向的是函数。
由于 int nArray[10]实际就是一个指针指向一个具有10个int的数组。当我们解引用这个指针时,通过*(nArray + index) 或者nArray[index]。
其实这个我们经常用到,数组名就是一个地址,也就是一个指针:nArray = int * nArray。 nArray[1] = *(nArray + 1)。
于是基于数组名是一个地址的思想,那么函数名是否是一个入口地址呢?
int foo(); foo实际也是一个指向函数的指针,当函数被调用时(通过()操作符),函数指针被解引用。
1. int (*fPoo)() 与 int *fPoo()的区别
由于优先级,int(*fPoo)() 可描述为:fPoo是一个指针,该指针指向一个函数,这个函数无参数,返回值为一个整型。而 int *fPoo()则可描述为:fPoo是一个函数,这个函数无参数,返回值为一个指向整型的指针。由此可以看出在int (*fPoo)() 中 fPoo “指向”任何函数只要能匹配(返回值,参数等)都可以。
2. ( a pointer to a function) 两个基本的情形。
(1) 将函数赋给一个指向函数的指针。
#include <iostream> using namespace std; inline int foo(int nX){ return nX; } inline void foo() { cout << "function pointer foo" << endl; } inline void goo() { cout << "function pointer goo" << endl; } int main() { int (*pFoo)(int) = foo; void (*pFun)() = foo; // pFoo 指向 foo pFun(); pFun = goo; // pFoo 现在指向 foo pFun(); cout << pFoo(6); return 0; }
由上面的代码写的很清楚,当然函数指针的使用要参数和返回类型进行匹配。
运行结果:
function pointer foo
function pointer goo
6
(2) 使用函数指针进行函数的调用。上面的代码也能说明这个情况就是通过函数指针进行的调用。
当然这里的调用方式不唯一,这种是隐式的调用,pFoo(6);这种调用看似就像普通函数调用一样。
还有一种是显示调用, (*pFoo)(6);
3 为什么要使用一个指针指向函数。
具体的应用需要具体的实现,需要看是否使用这种方法是比较不错的方法,举个例子:这个实例是在以前的一本书上看到过,类似的思想就是:当你在写一个函数执行一个任务时,例如排序,但是你想调用者自定义实现的任务的一部分(排序是升序或降序,也可先排奇数后排偶数等)
实例如下:
#include <iostream> #include <algorithm> // for swap using namespace std; template <class T> void SelectSort(T *nArray, const int nSize, bool (*pCompare)(T, T)); template <class T> bool Ascending(T nX, T nY); template <class T> bool Descending(T nX , T nY); template <class T> void PrintArray(T *nArray, const int nIndex); int main() { const int NUM = 6; float anArray[NUM] = { 23.2, 523.2, 224.15, 10.1, 262.6, -562.5 }; SelectSort(anArray, NUM, Descending); cout << "Descending: " << endl; PrintArray(anArray, NUM); SelectSort(anArray, NUM, Ascending); cout << "Ascending: " << endl; PrintArray(anArray, NUM); return 0; } template <class T> bool Descending(T nX , T nY) { return nX > nY; } template <class T> bool Ascending(T nX, T nY) { return nX < nY; } template <class T> void PrintArray(T *nArray, const int nIndex) { for (int i = 0; i < nIndex; ++i) cout << nArray[i] << "\t"; cout << endl; } template <class T> void SelectSort(T *nArray, const int nSize, bool (*pCompare)(T, T)) { int i, j, nIndex; for (i = 0; i < nSize; ++i) { nIndex = i; for (j = i + 1; j < nSize; ++j) { if (pCompare(nArray[j], nArray[nIndex])) nIndex = j; } swap(nArray[i], nArray[nIndex]); } }
运行结果: 正确(略)
当然这里不只是可以灵活实现升序和降序排,可以根据实际需要进行排序,通过此实例可以看出函数指针使得代码的reuse能力大大提高。
4. 函数指针与typedef
函数指针的形式,让我们一看就不是很习惯特别是刚开始使用指针的人,从而,使用typedef定义新类型,使得函数指针如同普通变量一样。
typedef bool (*pFunTest) (int nX);
解释:定义一个新类型:pFunTest, 这种类型就是指向函数的指针,而函数是带有一个形参和返回值为bool
有两种方式使用它:
(1)
bool Ok(int nX, int nY, bool (*pFun) (int nX)) ; // 有点难看
(2)
bool Ok(int nX, int nY, pFunTest pFun); // nice !! !就像普通变量一样
以上属个人愚见,也是对函数指针的总结,难免有不足之处或理解不到位的地方。