跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C/C++ 核心:函数指针与回调函数实战详解

回调函数是 C/C++ 中通过函数指针实现的重要机制。文章从函数指针的语法定义入手,解析了 typedef 别名、作为参数及返回值的用法,并重点阐述了回调函数的设计思想与应用场景。通过排序库函数调用和四则运算实例,展示了如何利用函数指针解耦调用者与被调用者,提升代码灵活性。内容涵盖同步与异步回调的区别,适合需要深入理解底层内存模型与动态调度机制的开发者阅读。

asphyx_a发布于 2026/3/16更新于 2026/6/2023 浏览
C/C++ 核心:函数指针与回调函数实战详解

回调函数预备知识

在深入理解回调函数之前,我们需要先掌握一个基础概念:函数指针。C 语言的灵魂是指针,我们常接触整型、字符或结构体指针,但函数指针指向的是代码本身。

什么是函数指针

函数指针也是指针,但它存储的不是变量的地址,而是函数的入口地址。定义语法如下:

返回类型 (*指针变量名)(参数类型列表);
  • 返回类型:被指向函数的返回值类型(如 int, void 等)。
  • 指针变量名:自定义的名称。
  • 参数类型列表:函数接受的参数类型。

这里有个关键点:括号不能省略。(*p) 的优先级高于 *,如果写成 return_type *p(args),编译器会将其解析为'返回值为指针的函数声明',而非函数指针。

为了方便使用,通常配合 typedef 定义别名:

// 定义一个函数指针类型 Fun1,指向返回 int、接受一个 int 参数的函数
typedef int (*Fun1)(int);

// 定义一个函数指针类型 Fun2,指向返回 void、无参数的函数
typedef void (*Fun2)(void);

如何调用函数指针

赋值时,函数名本身就代表地址,无需加 &。调用时直接像普通函数一样使用即可。

int Func(int x) { return x * 2; }

int main() {
    // 定义并初始化函数指针
    int (*p)(int) = Func;
    
    // 通过指针调用
    int result = p(5); // 等价于 Func(5)
    return 0;
}

函数指针作为参数和返回值

函数指针可以作为参数传递给其他函数,也可以作为函数的返回值。这在实现通用逻辑时非常有用。

#include <iostream>
using namespace std;

// 定义操作类型别名
typedef int (*Operation)(int, int);

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

// 接收函数指针作为参数
void calculate(int x, int y, Operation op) {
    cout << "Result: " << op(x, y) << endl;
}

int main() {
    calculate(10, 5, add); // 输出 Result: 15
    calculate(10, 5, sub); // 输出 Result: 5
    return 0;
}

此外,函数指针数组允许我们将多个函数组织在一起管理:

// 方法 1:直接定义
void (*func_array_1[5])(int, int, float);

// 方法 2:使用 typedef 简化
typedef void (*p_func_array)(int, int, float);
p_func_array func_array_2[5];

回调函数

什么是回调函数

回调函数本质上就是通过函数指针调用的函数。当你把函数的地址作为参数传给另一个函数,并在特定事件发生时由该函数调用这个地址指向的代码,这就构成了回调。

简单来说,就是把一段可执行的代码像参数一样传递出去,等待某个时刻被触发执行。如果立即执行是同步回调,稍后执行则是异步回调。

为什么要用回调函数

回调的核心价值在于解耦。调用者不需要知道具体是谁在执行任务,只需要约定好接口原型。这使得库函数可以处理通用逻辑,而将具体细节交给用户自定义的回调函数。

例如,标准库中的排序函数无法预知你要排序的对象结构,它可以通过回调函数让用户传入比较规则,从而实现灵活的排序策略。

实战示例

下面是一个完整的回调函数应用案例,展示了如何通过函数指针实现动态运算选择:

#include <iostream>
using namespace std;

// 定义操作函数指针类型
typedef float (*Operation)(float, float);

// 加法回调
float ADD(float a, float b) {
    cout << "a+b=" << a + b << endl;
    return a + b;
}

// 减法回调
float SUB(float a, float b) {
    cout << "a-b=" << a - b << endl;
    return a - b;
}

// 乘法回调
float MUL(float a, float b) {
    cout << "a*b=" << a * b << endl;
    return a * b;
}

// 除法回调
float DIV(float a, float b) {
    if (b == 0) {
        printf("Error: Division by zero!\n");
        return 0;
    }
    cout << "a/b=" << a / b << endl;
    return a / b;
}

// 通用处理函数,接收回调函数指针
float add_sub_mul_div(float a, float b, Operation op) {
    return op(a, b);
}

int main() {
    // 动态切换运算方式
    add_sub_mul_div(1.1, 2.2, ADD);
    add_sub_mul_div(1.1, 2.2, SUB);
    add_sub_mul_div(1.1, 2.2, MUL);
    add_sub_mul_div(1.1, 2.2, DIV);
    return 0;
}

在这个例子中,add_sub_mul_div 并不关心具体做什么运算,它只负责调用传入的 op 指针。主程序通过传入不同的函数名(即函数地址),实现了运行时的行为切换。

总结

回调函数是 C/C++ 中实现灵活架构的重要工具。通过函数指针,我们可以将控制流反转,让底层库函数主动调用上层业务逻辑。掌握这一机制,对于理解事件驱动模型、GUI 编程以及各类框架设计都至关重要。

目录

  1. 回调函数预备知识
  2. 什么是函数指针
  3. 如何调用函数指针
  4. 函数指针作为参数和返回值
  5. 回调函数
  6. 什么是回调函数
  7. 为什么要用回调函数
  8. 实战示例
  9. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • C++ 协程深度解析:从内部机制到实用场景
  • Java 时间类(中):JDK8 全新时间 API 详细教程
  • Apache IoTDB 时序数据库架构优势与选型指南
  • GitHub 专用代理配置指南
  • 后仿 SDF 反标 Warning 描述与解决方案
  • 国产 FPGA 低温低压测试问题反思与总结
  • ManiSkill 机器人模拟环境安装与使用指南
  • MySQL DDL 操作详解:数据库、数据表与字段管理
  • TI AFE5816:16 通道超声波模拟前端 (AFE)
  • 基于 FPGA 的日志及参数文件存储设计
  • AI 辅助编程:利用 GitHub Copilot 等工具提升开发效率
  • Java Web 学习:前端 HTML 基础与常用标签
  • 前端 API 设计最佳实践
  • 基于 Python 的旅游大数据分析与推荐系统设计与实现
  • Redmine 基于 Docker 的部署与插件配置指南
  • 大模型学习资料汇总与学习路线指南
  • AI 生成图片提示词:新手入门指南与最佳实践
  • 大模型在大数据平台的应用场景与开发落地实践
  • OpenClaw Agents 执行引擎深度解析:拆解 AI 的“思考与行动”核心
  • Java Web 拦截机制:Filter 与 Interceptor 对比实战

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online