【函数指针】

函数指针详解

什么是函数指针

函数指针是指向函数地址的指针变量。与普通指针存储变量地址不同,函数指针存储的是函数在内存中的地址。

cpp 复制代码
// 普通指针:存储变量地址
int a = 10;
int* p = &a;

// 函数指针:存储函数地址
void test() { std::cout << "hello" << std::endl; }
void (*p)() = test; // p存储test函数的地址

为什么需要函数指针

函数指针的核心价值是让函数像变量一样被传递,实现运行时动态选择执行的函数。

cpp 复制代码
void A() {}
void B() {}

void run(void (*f)()) {
    f(); // 执行传入的函数
}

run(A); // 执行A
run(B); // 执行B

这是工厂模式、策略模式等多种设计模式的基础。

直观理解

  • 普通变量:存储数据
  • 函数指针:存储行为(操作步骤)

核心区别:

数据指针指向数据,函数指针指向行为

应用场景

函数指针可以像数据一样存储在各种容器中:

  • map:实现注册模式(如插件系统)
  • vector:存储多个函数
  • 数组:实现简单的命令分发

语法

基本形式

cpp 复制代码
int add(int a, int b) { return a + b; }

// 函数指针定义
int (*p)(int, int) = add;
// 调用
int result = p(2, 3);

简化写法(typedef/using)

cpp 复制代码
// 传统写法
typedef int (*FuncType)(int, int);
// C++11+ 现代写法
using FuncType = int(*)(int, int);

FuncType p = add;

无参数/无返回值

cpp 复制代码
void hello() { std::cout << "Hello" << std::endl; }
void (*fptr)() = hello;
fptr();

作为参数

cpp 复制代码
void execute(void (*func)()) {
    func();
}

execute(hello);

作为返回值

推荐写法(使用typedef/using简化):

cpp 复制代码
using FuncType = int(*)(int, int);

FuncType getFunc() {
    return add;
}

// 1. 调用getFunc函数,获取add函数的指针
FuncType p = getFunc();
// 2. 调用add函数
int result = p(1, 2);

形式总结

场景 形式 示例
指针变量 返回类型 (*指针名)(参数列表) int (*p)(int, int) = add;
typedef/using typedef 返回类型 (*类型名)(参数列表) typedef int(*FuncType)(int, int);
作为参数 void f(返回类型 (*param)(参数列表)) void run(int (*func)(int, int))
作为返回值 typedef/using类型名 f() FuncType getFunc() { return add; }

关键规律(*名字) 必须用括号包起来,否则编译器会认为是函数声明。

本质

函数指针的本质是把函数当成"任务"传递

cpp 复制代码
void life(void (*f)()) {
    f(); // 执行传入的任务
}

void eat() { std::cout << "吃饭" << std::endl; }
life(eat); // 传递"吃饭"任务

简单来说:

普通参数传数据,函数指针传动作

实际应用

你可能已经在使用函数指针的概念,只是换了个名字:

  • 虚函数
  • std::function
  • Lambda表达式
  • 回调函数

这些底层都基于函数指针的思想。

复杂声明解析

对于复杂的函数指针声明:

cpp 复制代码
Plugin* (*FactoryFunc)();

解析:FactoryFunc 是一个返回 Plugin* 且无参数的函数指针。

总结

函数指针是C++中强大的特性,它允许我们:

  • 动态选择执行的函数
  • 实现回调机制
  • 构建灵活的设计模式
  • 提高代码的模块化和可扩展性

核心理解:普通指针指向数据,函数指针指向代码

相关推荐
一木 之林3 分钟前
插件、MCP、Skill 的区别?
java·c++·人工智能
ShineWinsu37 分钟前
对于MySQL:内置函数的解析
linux·数据库·c++·mysql·面试·函数·查询
程序猿编码3 小时前
纯C++轻量计算机视觉推理引擎:基于GGML的端侧CV模型部署技术全解析
开发语言·c++·计算机视觉·大模型·transformer
Tairitsu_H4 小时前
[C++] C++11新增构造:列表初始化和std::initializer_list
开发语言·c++·c++11·构造
hansang_IR4 小时前
【题解】P4456 [CQOI2018] 交错序列(矩阵乘法)
c++·线性代数·算法
光电笑映5 小时前
Linux 线程同步与互斥:锁的本质、条件变量与信号量的底层原理
linux·运维·服务器·开发语言·c++
jearry5 小时前
WebView2 原生拖放的桥接之道:拆解 yyzTools 的 drop-zone.js
前端·c++
零基础的修炼5 小时前
CUDA知识汇总
开发语言·c++·编辑器
欧特克_Glodon5 小时前
OpenCV计算机视觉开发入门与实践<三十八>:图像添加数字水印
c++·人工智能·opencv·计算机视觉
蒸蒸yyyyzwd6 小时前
与Redis和MySQL有关的知识
c++·求职招聘·八股