目录
第一性问题:什么是函数?为什么需要“函数指针”?
在 C++ 中,一个函数的作用就是:
将一段操作逻辑“封装起来”,并给它起个名字,以便反复调用。
int add(int a, int b) {
return a + b;
}
int result = add(1, 2); // 固定调用了名为 add 的函数
这一切都很好,但你会发现 —— 有些场景不够灵活:
如果我想把“函数”当作“参数”传进去呢?
int compute(int x, int y, ???)
我想要:
-
传进去一个函数
add
,就加法; -
传进去一个函数
mul
,就乘法。
能不能把“函数本身”当作一个变量来用?就像你传变量一样传函数?
答案是可以的!用函数指针!
什么是函数指针?
函数指针是一个指向函数入口地址的指针变量。函数本质上也是一段代码,它在内存中有地址。
就像:
-
你有一个电话本,里面存了朋友的电话号码。
-
函数指针就是电话号码,你可以通过它“拨打”某个函数,让它“接听”(执行)。
声明一个函数指针:
void printHello() {
std::cout << "Hello!" << std::endl;
}
int main() {
void (*ptr)() = printHello; // ptr 是一个函数指针,指向 printHello
ptr(); // 通过指针调用函数,效果等同于 printHello()
return 0;
}
-
ptr 是一个变量,但它不存数据,而是存了 printHello 函数的地址。
-
当你写 ptr();,就像拨打了 printHello 的“电话”,函数就被执行了。
int (*fp)(int, int);
含义是:
-
fp
是一个指针(*fp
) -
它指向一个函数
-
这个函数的返回值是
int
-
接受两个
int
参数
int add(int a, int b) { return a + b; }
int (*fp)(int, int) = add;
int result = fp(3, 4); // 等价于 add(3, 4)
typedef
简化函数指针
typedef int(*FuncPtr)(int, int);
意思是:
定义一个新的类型名 FuncPtr
,表示“返回 int、接受两个 int 参数的函数指针类型”。
这时你就可以用 FuncPtr
代替复杂的声明了!
逐步分析:
-
typedef
:我要给一个类型取个别名 -
int (*FuncPtr)(int, int)
:复杂类型:一个“指向函数的指针”-
FuncPtr
是名字 -
*FuncPtr
表示它是一个指针 -
(int, int)
表示它指向的是接受两个int
的函数 -
int
是函数的返回类型
-
//原写法:
int (*func)(int, int);
func = add;
//简化后
typedef int(*FuncPtr)(int, int);
FuncPtr func = add;
为什么需要函数指针?
假设你写了个程序,要根据用户选择执行不同操作:
-
如果用户选 1,调用 add。
-
如果用户选 2,调用 multiply。
传统方法可能是:
但如果有 100 个选择呢?代码会变得很长、很乱。
解决方案:动态选择
函数指针让你可以:
-
把所有可能的函数(add、multiply 等)存进一个“列表”(数组或变量)。
-
根据用户选择,取出对应的函数指针,然后直接调用。
比如:
void add(int a, int b) { std::cout << a + b << std::endl; }
void multiply(int a, int b) { std::cout << a * b << std::endl; }
int main() {
void (*funcPtr)(int, int); // 定义一个函数指针,可以指向任何接受两个 int 参数、无返回值函数
int choice;
std::cin >> choice;
if (choice == 1) funcPtr = add;
else funcPtr = multiply;
funcPtr(5, 3); // 根据选择调用对应的函数
return 0;
}
-
这里 funcPtr 就像一个“遥控器”,可以切换到不同的函数。
-
这种方式比写一大堆 if-else 更灵活、更简洁。
函数指针的底层原理
从底层看:
-
函数编译后在代码段中有个地址
-
函数名本身就是一个常量指针
-
所以:
fp = add;
是“把函数地址赋值给指针变量”
fp(2, 3); // 相当于跳转到指针指向的地址,执行那段代码
所以其实就是:“通过地址调用函数”。
什么时候用函数指针?
✅ 把函数作为参数传入(函数回调)
void run(int x, int y, int (*func)(int, int)) {
std::cout << "Result: " << func(x, y) << std::endl;
}
使用:
run(2, 3, add);
✅ 实现策略模式 / 动态选择算法
int multiply(int a, int b) { return a * b; }
run(5, 6, multiply); // 更灵活地“决定用哪个函数”
✅ 函数数组(用于菜单/状态机等)
int f1() { return 1; }
int f2() { return 2; }
int (*funcs[2])() = { f1, f2 };
std::cout << funcs[0]() << std::endl; // 调用 f1
总结
函数指针 = 可以把函数当变量传递和存储的机制,本质上是指向函数入口地址的指针,能实现灵活的回调与动态逻辑。