文章

C++函数指针

函数指针指向函数地址,可通过它调用函数,实现回调和动态绑定。

C++函数指针

C++ 函数指针

函数指针是 C++ 中一种保存函数地址的指针变量,允许像调用普通函数那样通过指针调用函数。它是理解回调机制、策略模式、以及 C/C++ 中函数灵活性的基础。

1
返回类型 (*函数指针名)(参数类型列表);
1
2
3
4
5
6
7
8
9
10
11
12
int add(int a, int b) {
    return a + b;
}

// 定义函数指针
int (*funcPtr)(int, int);

// 把函数地址赋给指针
funcPtr = add;

// 通过指针调用函数
int result = funcPtr(3, 4);  // 结果是 7

回调函数

排序比较器示例:

1
2
3
4
5
6
7
8
9
10
bool cmp(int a, int b) {
    return a > b;
}

void sort(int* arr, int n, bool (*cmpFunc)(int, int)) {
    for (int i = 0; i < n - 1; ++i)
        for (int j = i + 1; j < n; ++j)
            if (!cmpFunc(arr[i], arr[j]))
                std::swap(arr[i], arr[j]);
}

调用:

1
2
int arr[] = {3, 1, 5, 2};
sort(arr, 4, cmp);  // 使用 cmp 作为比较器

简化语法

使用 typedef

1
2
typedef int (*CalcFunc)(int, int);
CalcFunc f = add;

使用 using

1
2
using CalcFunc = int(*)(int, int);
CalcFunc f = add;

函数指针数组(策略表)

1
2
3
4
5
6
7
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

using CalcFunc = int(*)(int, int);
CalcFunc ops[] = {add, sub};

int result = ops[0](10, 5);  // 调用 add,结果是 15

对比

函数指针

1
2
3
int add(int a, int b) { return a + b; }
int (*fptr)(int, int) = add;
fptr(3, 4); // 结果 7
  • 开销低、语义清晰
  • 不能绑定状态、不支持捕获、不支持类成员函数

Lambda 表达式

1
2
3
4
5
auto f = [](int a, int b) { return a + b; };
f(3, 4); // 结果 7

int x = 10;
auto g = [x](int y) { return x + y; }; // 捕获外部变量
  • 有状态时是类对象(编译器生成),不能隐式转函数指针
  • 无捕获时可以自动转成函数指针

std::function

1
2
3
4
5
6
#include <functional>

std::function<int(int, int)> f = [](int a, int b) {
    return a + b;
};
f(3, 4); // 结果 7
  • 支持 lambda(有/无捕获)、函数指针、成员函数、仿函数
  • 内部封装复杂类型,易用但可能有堆内存开销
  • 推荐用于高抽象、插件系统、通用回调接口

虚函数指针

1
2
3
4
5
6
7
8
9
10
class Strategy {
public:
    virtual int apply(int a, int b) = 0;
    virtual ~Strategy() = default;
};

class Add : public Strategy {
public:
    int apply(int a, int b) override { return a + b; }
};
  • 支持接口多态(运行时绑定)
  • 类中通过虚函数表调用,支持成员状态
  • 有轻微开销(虚表指针跳转),但是面向对象设计核心
特性/维度函数指针Lambdastd::function虚函数指针
类型安全是(依赖函数签名匹配)是(编译器推导类型)是(模板封装类型安全)是(通过类层次保证)
可捕获变量(闭包)
运行时可替换性是(指向不同函数)是(可替换不同闭包)是(可存储不同可调用对象)是(运行时多态,虚表切换)
调用开销(性能)极低(等同普通函数调用)极低(无捕获时几乎零开销)略高(类型擦除,可能堆分配)低(一次虚表指针间接寻址)
存储/语法复杂度中(函数签名书写繁琐)简洁(尤其是内联定义)简洁(统一接口,代价是性能)中(需类定义和虚函数声明)
可用于类成员不能直接可以(成员或自由函数均可)可以(存储任意可调用对象)是(虚函数机制专用)
可用于策略/回调
是否编译期可求值无捕获时可(constexpr)
场景推荐方案理由
高性能、无状态策略(如 sort)函数指针 / 无捕获 Lambda快,简单
动态策略,有捕获std::function支持闭包
面向对象策略,多态结构虚函数扩展性强
编译期策略模板 / constexpr 函数编译时计算
小工具函数 / callbackLambda简洁、现代
本文由作者按照 CC BY 4.0 进行授权