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

相关推荐
一隅论数智3 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
weilx12343 天前
C++笔记-文件IO-<fcntl.h>
c++
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
Smileyqp沛沛3 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
深圳老胡3 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·3 天前
C++ 萌新语法入门篇
c++·算法比赛