【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❌/⚠️可能模糊,非标准,易错

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code bean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值