跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 函数包装器
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++函数包装器 = == 介绍 == '''函数包装器(Function Wrapper)'''是C++标准模板库(STL)中的一个重要概念,它提供了一种通用的方式来存储、复制和调用各种可调用对象(如函数指针、成员函数指针、函数对象和lambda表达式)。在C++中,函数包装器主要通过<code>std::function</code>类模板实现。 函数包装器的主要作用是: * 统一处理不同类型的可调用对象 * 实现回调机制 * 增强代码的灵活性和可维护性 == 基本语法 == <code>std::function</code>的基本声明形式为: <syntaxhighlight lang="cpp"> #include <functional> std::function<返回值类型(参数类型列表)> 包装器名称; </syntaxhighlight> == 使用示例 == === 包装普通函数 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> int add(int a, int b) { return a + b; } int main() { std::function<int(int, int)> func = add; std::cout << "Result: " << func(3, 4) << std::endl; // 输出: Result: 7 return 0; } </syntaxhighlight> === 包装lambda表达式 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> int main() { std::function<int(int, int)> func = [](int a, int b) { return a * b; }; std::cout << "Result: " << func(5, 6) << std::endl; // 输出: Result: 30 return 0; } </syntaxhighlight> === 包装成员函数 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> class Calculator { public: int subtract(int a, int b) { return a - b; } }; int main() { Calculator calc; std::function<int(Calculator&, int, int)> func = &Calculator::subtract; std::cout << "Result: " << func(calc, 10, 3) << std::endl; // 输出: Result: 7 return 0; } </syntaxhighlight> == 类型擦除 == <code>std::function</code>实现了'''类型擦除'''技术,这意味着它可以存储任何符合签名的可调用对象,而不需要知道具体类型。这是通过模板特化和虚函数等技术实现的。 <mermaid> classDiagram class function { +operator()() -target -invoker } note for function "隐藏了实际可调用对象的类型" </mermaid> == 实际应用场景 == === 回调机制 === 函数包装器常用于实现回调机制,特别是在事件驱动编程中: <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> #include <vector> class Button { std::function<void()> onClick; public: void setOnClick(std::function<void()> callback) { onClick = callback; } void click() { if (onClick) onClick(); } }; int main() { Button btn; btn.setOnClick([]() { std::cout << "Button clicked!" << std::endl; }); btn.click(); // 输出: Button clicked! return 0; } </syntaxhighlight> === 策略模式 === 函数包装器可以简化策略模式的实现: <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> #include <vector> class Sorter { std::function<bool(int, int)> compare; public: Sorter(std::function<bool(int, int)> comp) : compare(comp) {} void sort(std::vector<int>& data) { for (size_t i = 0; i < data.size(); ++i) { for (size_t j = i + 1; j < data.size(); ++j) { if (compare(data[i], data[j])) { std::swap(data[i], data[j]); } } } } }; int main() { std::vector<int> numbers = {5, 2, 8, 1, 9}; // 升序排序 Sorter ascending([](int a, int b) { return a > b; }); ascending.sort(numbers); for (int n : numbers) std::cout << n << " "; // 输出: 1 2 5 8 9 std::cout << std::endl; // 降序排序 Sorter descending([](int a, int b) { return a < b; }); descending.sort(numbers); for (int n : numbers) std::cout << n << " "; // 输出: 9 8 5 2 1 std::cout << std::endl; return 0; } </syntaxhighlight> == 性能考虑 == 使用<code>std::function</code>会有一定的性能开销,主要包括: * 动态内存分配(某些情况下) * 间接函数调用 * 类型擦除带来的额外开销 在性能敏感的代码中,可以考虑直接使用函数指针或模板参数。 == 与函数指针的比较 == {| class="wikitable" |- ! 特性 !! <code>std::function</code> !! 函数指针 |- | 可调用对象类型 || 支持函数、lambda、函数对象等 || 仅支持普通函数 |- | 捕获状态 || 可以 || 不可以 |- | 性能 || 较低 || 较高 |- | 灵活性 || 高 || 低 |} == 高级用法 == === 绑定参数 === 可以结合<code>std::bind</code>使用,实现参数绑定: <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> int multiply(int a, int b, int c) { return a * b * c; } int main() { using namespace std::placeholders; // 绑定第一个参数为2,第三个参数为3 std::function<int(int)> func = std::bind(multiply, 2, _1, 3); std::cout << "Result: " << func(5) << std::endl; // 输出: Result: 30 (2*5*3) return 0; } </syntaxhighlight> === 函数组合 === 可以创建高阶函数,实现函数组合: <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> template <typename F, typename G> auto compose(F f, G g) { return [=](auto x) { return f(g(x)); }; } int main() { std::function<int(int)> square = [](int x) { return x * x; }; std::function<int(int)> increment = [](int x) { return x + 1; }; auto squareThenIncrement = compose(increment, square); std::cout << "Result: " << squareThenIncrement(3) << std::endl; // 输出: 10 (3² + 1) return 0; } </syntaxhighlight> == 数学表示 == 从数学角度看,函数包装器可以表示为: <math> f: X \rightarrow Y </math> 其中<math>X</math>是参数类型,<math>Y</math>是返回类型。 == 注意事项 == * 检查<code>std::function</code>是否为空(使用<code>operator bool</code>) * 注意生命周期问题,避免悬垂引用 * 在性能关键路径上谨慎使用 == 总结 == <code>std::function</code>是C++中处理各种可调用对象的强大工具,它提供了统一的接口和极大的灵活性。虽然有一定的性能开销,但在大多数应用场景中,这种开销是可以接受的。理解并熟练使用函数包装器,可以显著提高C++代码的表达能力和可维护性。 [[Category:编程语言]] [[Category:C++]] [[Category:C++stl 函数对象]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)