C++ 笔记 function 函数包装器模板

在 C++11 及以后的标准中,std::function 是一个极具价值的函数包装器模板 ,隶属于<functional>头文件。它能统一封装所有可调用对象 (普通函数、函数指针、仿函数、Lambda 表达式、类成员函数等),形成一个通用、可赋值、可存储的函数对象,让 C++ 的回调、策略模式、函数管理变得更加简洁优雅。

本文从核心概念、用法、场景、示例全方位讲解std::function,帮你快速掌握这个现代 C++ 必备工具。

一、什么是 std::function?

1. 核心定义

std::function 是一个通用、类型安全的可调用对象包装器

它是一个模板类,可以 "包裹" 任何符合签名的可调用对象;

对外提供统一的调用接口,无视底层可调用对象的类型;

可以像普通变量一样赋值、拷贝、存储、作为参数传递

简单理解:std::function = 万能函数容器,只要返回值和参数一致,任何可调用对象都能装进去。

2. 语法格式

cpp 复制代码
#include <functional>  // 必须包含

// 格式:
std::function<返回值类型(参数类型1, 参数类型2...)> 变量名;

示例:定义一个能包装 "接收两个 int、返回 int" 的函数包装器

cpp 复制代码
function<int(int, int)> func;

二、std::function 能包装什么?

std::function 可以统一包装4 大类可调用对象

1. 普通函数

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

function<int(int, int)> f = add;
cout << f(10, 20) << endl;  // 30
  1. Lambda 表达式(最常用)
cpp 复制代码
function<int(int, int)> f = [](int a, int b) { return a * b; };
cout << f(10, 20) << endl;  // 200
  1. 仿函数(函数对象)
cpp 复制代码
class Sub {
public:
    int operator()(int a, int b) { return a - b; }
};

function<int(int, int)> f = Sub();
cout << f(20, 10) << endl;  // 10
  1. 类成员函数(需绑定对象)
cpp 复制代码
class Test {
public:
    int mul(int a, int b) { return a * b; }
};

Test obj;
function<int(Test&, int, int)> f = &Test::mul;
cout << f(obj, 10, 20) << endl;  // 200

三、核心优势:为什么要用 function?

1. 统一所有可调用对象类型

没有function时,不同可调用对象类型不同,无法存入同一个容器;有了function类型不同、功能相同的函数可以统一管理

示例:同一容器存储不同类型函数

cpp 复制代码
#include <iostream>
#include <functional>
#include <vector>
using namespace std;

int main() {
    // 统一函数签名:int(int,int)
    vector<function<int(int, int)>> vec;

    // 放入 普通函数、Lambda、仿函数
    vec.push_back([](int a,int b){return a+b;});
    vec.push_back([](int a,int b){return a*b;});

    cout << vec[0](10,20) << endl;  // 30
    cout << vec[1](10,20) << endl;  // 200
    return 0;
}

2. 轻松实现回调函数

以往用函数指针实现回调,语法复杂、不支持 Lambda / 仿函数;

function 让回调简单、直观、灵活

示例:回调函数

cpp 复制代码
// 接收一个function作为回调
void doWork(function<void()> callback) {
    cout << "执行任务..." << endl;
    callback();  // 调用回调
}

int main() {
    doWork([](){ cout << "回调执行!" << endl; });
    return 0;
}

3. 可重新赋值,灵活切换函数

普通函数指针赋值受限,function 可以随时更换包装的函数

cpp 复制代码
function<int(int,int)> f;

f = [](int a,int b){return a+b;};
cout << f(10,20);  // 30

f = [](int a,int b){return a*b;};
cout << f(10,20);  // 200

四、完整使用示例(全能演示)

cpp 复制代码
#include <iostream>
#include <functional>
using namespace std;

// 1. 普通函数
int add(int a, int b) { return a + b; }

// 2. 仿函数
class Mul {
public:
    int operator()(int a, int b) { return a * b; }
};

int main() {
    // 定义function包装器:int(int,int)
    function<int(int, int)> func;

    // 包装普通函数
    func = add;
    cout << "add: " << func(10, 20) << endl;

    // 包装Lambda
    func = [](int a, int b) { return a - b; };
    cout << "sub: " << func(20, 10) << endl;

    // 包装仿函数
    func = Mul();
    cout << "mul: " << func(10, 20) << endl;

    return 0;
}

输出:

cpp 复制代码
add: 30
sub: 10
mul: 200

五、常用场景

std::function 在实际开发中高频使用:

  1. 回调函数:按钮点击、异步完成、事件触发;
  2. 策略模式:动态切换算法逻辑(排序、过滤、处理规则);
  3. 函数容器 :把函数存入vector/map统一管理;
  4. 延迟执行:保存函数,后续再调用;
  5. 替代复杂函数指针:语法更简洁、可读性更高。

六、注意事项

  1. 必须包含头文件<functional>
  2. 包装时签名必须一致:返回值 + 参数类型必须严格匹配;
  3. 空 function 调用会抛异常 :使用前可判断if(func)
  4. 包装成员函数时:必须传入对象作为第一个参数;
  5. 性能极高:几乎无额外开销,可放心使用。

总结

  1. std::function :C++11 函数包装器,统一封装所有可调用对象
  2. 包装类型:普通函数、Lambda、仿函数、类成员函数;
  3. 核心价值:统一类型、实现回调、灵活赋值、管理函数集合;
  4. 语法function<返回值(参数)>
  5. 地位 :现代 C++ 回调、函数管理的标准方案

std::function 让 C++ 的函数操作更加现代化、优雅化,是必须掌握的核心模板。

相关推荐
用户8055336980315 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
RainCity16 小时前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
BadBadBad__AK1 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境2 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境2 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴3 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
卷无止境5 天前
C++ 的Eigen 库全解析
c++
卷无止境5 天前
现代 C++特性大盘点:一门脱胎换骨的老语言
c++·后端
郝学胜_神的一滴5 天前
CMake 27:缓存变量的特性、语法、类型与实操全解
c++·cmake
博客18007 天前
酷宝的使用方法,超好用的免费界面库,C++、MFC可用
c++·mfc·界面库·库来帮·酷宝