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 小时前
tinyxml2 常用读取接口对照表
xml·c++·tinyxml2
MC皮蛋侠客3 小时前
C++中使用Redis指南:基于redis-plus-plus库
开发语言·c++·redis
星晨雪海3 小时前
Redis-逻辑查询详情讲解
java·开发语言
大鹏说大话3 小时前
Java线程池调优实战:从核心参数到避坑指南
java·开发语言
lolo大魔王3 小时前
Go语言的基础语法
开发语言·后端·golang
小陈工3 小时前
Python Web开发入门(八):用户认证系统实现,给你的应用加上安全锁
开发语言·前端·数据库·python·安全·django·sqlite
铅笔侠_小龙虾3 小时前
Miniconda + Poetry 实战
开发语言·python
深海空无一人4 小时前
python基础
开发语言·python
泡泡茶壶Wending4 小时前
opengl笔记之VBO,VAO
笔记