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++ 的函数操作更加现代化、优雅化,是必须掌握的核心模板。

相关推荐
handler0122 分钟前
从零实现自动化构建:Linux Makefile 完全指南
linux·c++·笔记·学习·自动化
Ulyanov27 分钟前
《PySide6 GUI开发指南:QML核心与实践》 第二篇:QML语法精要——构建声明式UI的基础
java·开发语言·javascript·python·ui·gui·雷达电子对抗系统仿真
码界筑梦坊30 分钟前
357-基于Java的大型商场应急预案管理系统
java·开发语言·毕业设计·知识分享
anzhxu35 分钟前
Go基础之环境搭建
开发语言·后端·golang
yu85939581 小时前
基于MATLAB的随机振动仿真与分析完整实现
开发语言·matlab
赵钰老师1 小时前
【结构方程模型SEM】最新基于R语言结构方程模型分析
开发语言·数据分析·r语言
guygg881 小时前
利用遗传算法解决列车优化运行问题的MATLAB实现
开发语言·算法·matlab
gihigo19981 小时前
基于MATLAB实现NSGA-III的土地利用空间优化模型
开发语言·matlab
Hello_Embed1 小时前
嵌入式上位机开发入门(二十六):将 MQTT 测试程序加入 APP 任务
网络·笔记·网络协议·tcp/ip·嵌入式
不会编程的懒洋洋2 小时前
C# Task async/await CancellationToken
笔记·c#·线程·面向对象·task·同步异步