前言
函数的二进制代码存放在内存四区中的代码段,函数的地址是它在内存中的起始地址(即每个函数都有一个入口地址)。函数指针就指向这个起始地址,将函数指针作为参数,就可以调用该函数
一、使用函数指针的三个步骤
- 声明函数指针
普通指针,需要给它一个类型,如 int* a 或 char* a ;同理,函数指针也需要给它一个类型。这个类型指的是函数的返回值和参数类型和顺序(函数名和实参名不是。可以这样理解,指针是指向一个地址,取什么名字都行,只是一个名称罢了)
如果函数原型为:
// 下面两个函数的返回值、参数类型和顺序一样
int func1(int a,string str);
int func2(int b,string name);
bool func3(int age,string name);
bool func4(int age);
则函数指针为(注意以下两点):
int (*func)(int a,string str);
bool (*pfunc3)(int ,string); // 1、形参可以不写,只保留类型即可
bool (*pf4)(int); // 2、指针名无所谓,随便自己定义一个都行(但不要和函数名相同)
- 初始化函数指针
声明了函数指针,肯定要让它指向函数的入口地址,而函数名就是这个地址,所以初始化如下:
函数指针名 = 函数名
pfunc3 = func3 // 如果函数指针名与函数名相同,这里就会出现歧义
- 使用函数指针调用函数
(*函数指针名)(实参); // c/c++通用,推荐使用这个
函数指针名(实参); // c++
(*pfunc3)(实参1,实参2);
二、应用场景——回调函数
函数指针最常用的方式就是回调函数,这在多线程和网络通讯中很常见
那回调函数是什么意思呢?
简单来说,就是在一个主体函数中调用另一个功能函数。
那为什么要这样做,而不是直接把该功能函数写进主体函数里?
因为功能函数的种类可以有很多,假设主体函数是输入一串数字,然后按照一定的规则排序,最后再输出排序后的数字。这里的规则有很多,比如从大到小,从小到大,从中间开始到大再到小等等,可以把这些规则都写进主体函数中,在明确要使用哪个规则,但这样主体函数的代码量就会非常多。这时就可以使用回调函数:把排序规则在外面写成一个功能函数,想要哪种排序就写哪种,然后使用函数指针让主体函数来调用自己写的规则函数即可。
示例代码:
#include <iostream>
using namespace std;
void func1(string a){ cout <<"升序" << a << endl;}
void func2(string a){ cout <<"降序" << a << endl;}
void func3(string a){ cout <<"中间排序" << a << endl;}
void sort(string n, void (*pfunc)(string)) // 1、声明函数指针
{
cout <<"将一串数字:"<<n<<"解析为多个数字"<<endl;
(*pfunc)(n); // 调用函数
cout << "返回排序后的数字" << endl;
}
int main()
{
string num = "348963";
sort(num, func1); // 2、函数指针赋值
// sort(num, func2);
// sort(num, func3);
}