指针的本质就是内存地址,如果该内存地址存放的是某个数据,那么这个指针就是常见的数据指针。同样,如果这个内存地址中存放的是某个函数,那么这个指针就是函数指针。
定义一个函数指针:
void (*pFunc)(int);
如果要定义多个同一类型的指针,还可以使用typedef定义一种新的函数指针的数据类型:
typedef void(*PFUNC)(int);
这样就可以使用这种新的数据类型定义函数指针:
PFUNC pFunc1; PFUNC pFunc2;
这些函数指针可以指向多个相同类型的函数。
函数指针可以使用函数名来赋值,如有一func()函数:
pFunc1 = func(); //前面也可以添加&
1 用函数指针调用函数
当需要在多个函数中根据条件来判断函数调用时,通过使用函数指针可以让函数调用更灵活、轻便。
#include <iostream>
using namespace std;
void pass(int score){cout<<"score:"<<score<<",passed!"<<endl;}
void fail(int score){cout<<"score:"<<score<<",not passed!"<<endl;}
void excell(int score){cout<<"score:"<<score<<",excellent!"<<endl;}
void main()
{
int score = 0;
do{
cout<<"请输入一个分数(-1时结束):";
cin>>score;
void (*pfunc)(int);
if(score<60) pfunc = fail;
else if(score>=60 && score<90) pfunc = pass;
else pfunc = excell;
(*pfunc)(score);
}while(score != -1);
}
2 函数指针实现回调函数
回调函数就是函数指针指向的函数。
主调函数使用函数指针作为参数,相当于就是将回调函数嵌入(包裹)到了主调函数之中。
回调函数可以实现算法的通用性。例如排序算法,你可以定义好算法的通用框架,至于其中核心的算法逻辑,则留待回调函数去完成,用户可以通过不同的回调函数,轻松简单地实现各种算法,对算法进行自定义。
3 记住状态的函数对象
如果不使用全局变量或静态变量,函数是无法记住上一次调用时的状态的。
对于类,可以重载操作符“()”,重载“()”操作符后的类成为一个函数对象。当对象使用操作符函数时,可以更新对象的属性,就相当于保存了函数对象的状态。
附代码1
//DetectPass.h #include <string> #include <iostream> using namespace std; enum PassStatus {pass,failed,reject}; //枚举类型定义密码状态 class DetectPass { public: DetectPass(); ~DetectPass(); PassStatus operator() (string passstr); //括号操作符重载 protected: int numOfRun; //用成员数据记录输入密码的次数(对象状态) string getpass(); //(模拟)通过数据库获取密码 }; //DetectPass.cpp //#include "DetectPass.h" DetectPass::DetectPass() { cout <<"构造函数对象..." <<endl; numOfRun=0; } DetectPass::~DetectPass() { cout <<"析构函数对象..." <<endl; } PassStatus DetectPass::operator() (string passstr) { cout <<"这是第" <<++numOfRun <<"次输入密码,";//状态更新 if (numOfRun<=3) { if (passstr.compare(getpass())==0)//passstr是string类型,有compare()成员方法 { cout <<"密码正确。" <<endl <<"欢迎进入系统!" <<endl; return pass; } else { cout <<"密码错误!" <<endl; return failed; } } else { cout <<"您已经输错密码三次!异常退出!" <<endl; return reject; } } string DetectPass::getpass() { return string("123456"); } //main.cpp //#include "DetectPass.h" //#include <string> //#include <iostream> using namespace std; DetectPass password; //声明一个与password函数同名的对象 int main() { string input; do { cout <<"请输入密码:"; cin >>input; }while(password(input)==failed); //看起来像是调用password函数 cin.get();cin.get(); return 0; } /* 构造函数对象... 请输入密码:123 这是第1次输入密码,密码错误! 请输入密码:456 这是第2次输入密码,密码错误! 请输入密码:123456 这是第3次输入密码,密码正确。 欢迎进入系统! */
附代码2
#include <iostream> using namespace std; template <typename T> class mymax { public: T operator()(T a, T b)//重载“()”操作符,在这个操作符中实现具体功能 { return a>b?a:b; } };// 重载“()”操作符后的类成为一个函数对象 template <typename T>// 利用函数对象定义函数模板,可以理解为函数指针作为回调函数 T compare(T a, T b, mymax<T>& op) { return op(a,b); // 利用传递进来的函数对象进行具体的比较操作 } void main() { mymax<int> intmax;// 定义一个int类型的函数对象 int nMax = intmax(3,4);//直接使用函数对象 // 编译器行为:int nMax = intmax.operator()(3,4); cout<<nMax<<endl; nMax = compare(5,6,intmax);//将函数对象作为参数传递给其他函数 cout<<nMax<<endl; system("pause"); } /* 4 6 */