函数指针
函数指针的声明形式
数据类型 (*函数名)(形参列表)
函数指针的作用
我们知道函数与函数形参是两个不太一样的概念:
函数体 | 动作 |
函数形参 | 数据 |
在内存中,不管是动作还是数据都使用16进制的数据存储在内存当中,用地址来访问。其实将函数作为一个地址来进行访问就相当于“将动作数据化”。这样的话,我们就做到了“一切皆可使用地址来访问”。这样做给我们带来的优势如下:
内存中的数据均有其对应的地址,我们可以将这些地址封装在一个数组中,对他们使用统一的格式进行访问,这样的程序条理清晰对象明确,例如:
对象 | 动作 |
小明,小李 | 约会 |
小明,小强 | 吃饭 |
大明,李四 | 看电影 |
大明,小明 | 看电影 |
我们可以编写如下程序实现上述函数功能:
函数指针的应用
函数的嵌套使用
#include <iostream>
using namespace std;
//using f1 = void(*)(int*, int*); // 相当于定义一个函数指针的模板
typedef void(*f1)(int*, int*); // 相当于定义一个函数指针的模板(与前面这一行代码作用相同)
void swap1(int* a, int* b)
{
int temp = 0;
temp = *a;
*a = *b;
*b = temp;
}
void Operation(int* a, int* b, f1 Fun)
{
Fun(a, b);
}
int main()
{
int a = 2, b = 4;
Operation(&a, &b, swap1);
cout << a << endl;
cout << b << endl;
}
以上实例,展示了在某一个函数中使用其他函数的示例,这种调用方式打破了“只可以在该函数内使用该函数之前定义过或声明过的函数”的规定,使用起来很方便,使得函数也可以像数据一样传入其他函数中使用。
C语言的“面向对象”结构体
C语言最重要的复合数据类型就是结构体,但是我们一般不知道的是“结构体也可以是想面向对象的功能”。面向对象最简单的解释就是“结构体 = 数据(数据成员) + 数据处理(函数)”,当我们输入数据后,这个结构体就如同黑箱一样,有许多外围接口可以供我们得到我们想要的结果,但是其中的过程并不是我们想关注的,C风格的面向对象的简单示例:
#include <iostream>
using namespace std;
struct Student
{
// 数据成员
int StudNum;
float Mark;
float Height;
float Weight;
// 数据处理
bool (*TestExam)(float Height, float Weight, float Mark);
void (*ShowInf)(int StudNum, float Height, float Weight, float Mark, bool (*TestExam)(float,float,float));
};
bool Student_TestExam(float Height, float Weight, float Mark)
{
if (Height > 175 && Weight < 150 && Mark>90)
{
return 1;
}
else
{
return 0;
}
}
using Func_TestExam = bool(*)(float, float, float);
void Student_ShowInf(int StudNum,float Height, float Weight, float Mark,Func_TestExam TestExam)
{
bool temp = TestExam(Height, Weight, Mark);
if (temp == 1)
{
cout << "学号为" << StudNum << "的同学综合成绩合格" << endl;
}
else
{
cout << "学号为" << StudNum << "的同学综合成绩不合格" << endl;
}
}
int main()
{
Student Stud1 = { 7,176,120,95 };
Stud1.TestExam = Student_TestExam;
Stud1.ShowInf = Student_ShowInf;
Stud1.ShowInf(Stud1.StudNum, Stud1.Height, Stud1.Weight, Stud1.Mark, Stud1.TestExam);
}
如上程序,我们实现了一个类似于“封装类”的结构体,实现功能如下:
输入数据 | 学生的学号,学生的体重,学生的身高,学生的期末成绩 |
输出数据 | 该学生的综合评测是否合格 |
函数指针实现类似于多态的功能
#include <iostream>
using namespace std;
typedef int (*Func)(int, int);
int Minus(int a, int b)
{
return a - b;
}
int Add(int a, int b)
{
return a + b;
}
int main()
{
Func operation;
operation = Minus;
cout << operation(1, 3) << endl;
operation = Add;
cout << operation(1, 3) << endl;
}
我们从上述例程看到:相同的函数operation在赋予了两个不同的函数实现过程之后,输入相同的形参可以进行“返回值相同,形参相同但是实现方式不同”的数据操作。这一点有点像多态,但是与“C++中面向对象的多态”还是有一定的差距的。
三种声明函数指针的方式
// 方法一:
typedef int(*FuncName)(int, int); // FuncName为函数类型名,Func1为函数指针名
FuncName Func1;
// 方法二:
using FuncName = int(*)(int, int); // FuncName为函数类型名,Func1为函数指针名
FuncName Func1;
// 方法三:
int(*Func1)(int, int) = Function; // Function在这里是已经实现的函数的函数名字