c++ 函数指针(Function Pointer)

目录

第一性问题:什么是函数?为什么需要“函数指针”?

什么是函数指针?

typedef 简化函数指针 

为什么需要函数指针?

函数指针的底层原理 

什么时候用函数指针?

总结


第一性问题:什么是函数?为什么需要“函数指针”?

在 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

总结

函数指针 = 可以把函数当变量传递和存储的机制,本质上是指向函数入口地址的指针,能实现灵活的回调与动态逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值