优秀的编程知识分享平台

网站首页 > 技术文章 正文

C++从函数指针(调用函数、实现回调函数)到记住状态的函数对象

nanyue 2024-07-26 15:44:07 技术文章 3 ℃

指针的本质就是内存地址,如果该内存地址存放的是某个数据,那么这个指针就是常见的数据指针。同样,如果这个内存地址中存放的是某个函数,那么这个指针就是函数指针。

定义一个函数指针:

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
*/
最近发表
标签列表