当前位置: 首页 > news >正文

【C++】C++函数指针详解与实用技巧

C++函数指针详解与实用技巧

在C++中,**函数指针(Function Pointer)**是一种强大而灵活的工具,常用于回调机制、策略模式、事件处理等场景。本文将从概念、语法、常见用法到实战示例,带你全面掌握C++函数指针。


🧠 什么是函数指针?

函数指针本质上是一个指针,它指向一个函数的入口地址,就像普通指针指向内存中的数据一样。

例如,一个函数如下:

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

我们可以定义一个指针,指向这个函数,然后通过指针来调用它。


🧱 函数指针的基本语法

函数指针的定义语法有点绕,但遵循以下模板就能掌握:

返回类型 (*指针变量名)(参数类型列表);

add 为例,它的函数指针定义如下:

int (*funcPtr)(int, int);  // 声明函数指针
funcPtr = add;             // 指向函数
int result = funcPtr(3, 4);  // 调用函数

💡 注意:函数名本身就是指向函数的指针,add&add 等价。


🧩 函数指针的常见用途

1️⃣ 替代 if-else/switch:简化逻辑选择

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }int main() {int (*op)(int, int);char choice = '+';if (choice == '+') op = add;else if (choice == '-') op = sub;std::cout << "Result: " << op(10, 5) << std::endl;
}

2️⃣ 作为函数参数(回调机制)

void process(int a, int b, int (*op)(int, int)) {std::cout << "Result: " << op(a, b) << std::endl;
}int add(int a, int b) { return a + b; }int main() {process(3, 4, add);
}

3️⃣ 返回函数指针(高级用法)

int multiply(int a, int b) { return a * b; }int (*getOperation())(int, int) {return multiply;
}int main() {auto op = getOperation();std::cout << "Result: " << op(6, 7) << std::endl;
}

4️⃣ 使用数组存储多个函数指针(策略切换)

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }int main() {int (*ops[3])(int, int) = { add, sub, mul };int choice = 2;  // 使用第3个函数(mul)std::cout << "Result: " << ops[choice](3, 5) << std::endl;
}

🧼 函数指针 vs std::function

在现代C++中,推荐使用 std::function 来代替裸函数指针,它更安全,能包装函数、Lambda表达式、成员函数等:

#include <functional>std::function<int(int, int)> op = [](int a, int b) {return a * b;
};
std::cout << op(4, 5);  // 输出 20

🚀 如果你用的是 C++11 及以上版本,请优先考虑 std::functionLambda 表达式。


🧭 总结

特性描述
本质指向函数地址的指针
作用支持回调机制、动态策略选择
使用难点语法略显复杂,注意括号位置
推荐替代方案std::function、Lambda 表达式

函数指针虽在现代C++中使用频率下降,但在系统编程、嵌入式开发、回调机制等场景中仍有不可替代的价值。


📌 提问环节

QT中在connect函数中,第二参数使用了&对函数进行取地址,是否是多此一举呢?

答案是:不,多此一举——是必要的“好习惯”或“为了清晰性”


👇 来看这个典型用法:

QObject::connect(button, &QPushButton::clicked, this, &MyClass::onButtonClicked);

🤔 &QPushButton::clicked 为什么还要加 &,难道 QPushButton::clicked 本身不是函数指针吗?


✅ 理论上:是的,确实可以不加 &

在C++中,函数名本身就可以衰变(decay)为指针。也就是说,这样写:

QObject::connect(button, QPushButton::clicked, this, MyClass::onButtonClicked);

在部分情况下也能通过编译,但在 Qt 的宏系统(尤其是旧版本或使用 Qt 元对象编译器 moc 的语法检查)中,会产生二义性、模糊错误或编译失败。


✅ 实际上:加 & 更清晰、更兼容、更安全

  • 明确表示取地址,避免阅读歧义
  • 支持 Qt5/Qt6 的 lambda、函数指针、重载函数等一致写法
  • 对有重载信号的类,比如 QComboBox::activated,必须用 & 明确指定版本

✍ 举例(必须使用 & 才能工作):

QObject::connect(comboBox,static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),this,&MyClass::onIndexChanged);

🔔 小结:

写法是否能编译是否推荐说明
&QPushButton::clicked明确、兼容、推荐
QPushButton::clicked❌/⚠️可能模糊,非标准,易错

结论:加 & 虽然在某些情况下是“多余”的,但为了兼容性和代码清晰性,绝不是多此一举,反而是推荐做法。

相关文章:

  • 小白借助ai对全栈进行浅浅理解(学习笔记)-Lambda、Optional 避免空指针与新的日期时间 API
  • 南邮计科电工电子实验第五次课与非门设计数字锁逻辑电路小测答案
  • 线程池的核心参数和线程创建方式,线程和进程
  • 介绍Unity中的Dictionary
  • 【RAG技术全景解读】从原理到工业级应用实践
  • 树莓派5+Ubuntu24.04 LTS串口通信 保姆级教程
  • Mockoon 使用教程
  • 解决:‘java‘ 不是内部或外部命令,也不是可运行的程序-Java环境变量配置(含JDK8、JDK21安装包一站式配置)
  • 垃圾厌氧堆肥发酵实验台试验装置
  • 直接用字符串方式 split(“。“) 来切句,虽然能把句子拆开,但无法和 BERT 模型的 token 位置对应(embedding 用不上)
  • 两种方法求解最长公共子序列问题并输出所有解
  • Android学习总结之算法篇八(二叉树和数组)
  • 可视化图解算法35:在二叉树中找到两个节点的最近公共祖先(二叉树的最近公共祖先)
  • 【LeetCode】删除排序数组中的重复项 II
  • 2025年渗透测试面试题总结-某步在线面试(题目+回答)
  • 开启智能Kubernetes管理新时代:kubectl-ai让操作更简单!
  • ZooKeeper工作机制与应用场景
  • 邻近标记技术:研究蛋白互作的利器(五)
  • base64与图片的转换和预览(高阶玩法)
  • 守护数字家园:个人博客安全防护指南
  • 第一集|《刑警的日子》很生活,《执法者们》有班味
  • 融创中国:今年前4个月销售额约112亿元
  • OpenAI任命了一位新CEO
  • 马新民卸任外交部条约法律司司长
  • 太原一高中生指出博物馆多件藏品标识不当,馆方已邀请他和专家共同探讨
  • 戴维·珀杜宣誓就任美国驻华大使