跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 函数适配器
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++函数适配器 = == 介绍 == '''函数适配器(Function Adapters)'''是C++标准模板库(STL)中用于修改或扩展函数对象行为的工具。它们通过包装现有的函数对象、函数指针或成员函数,改变其调用方式或参数数量,从而增强代码的灵活性和复用性。 在STL中,函数适配器主要分为三类: * '''绑定器(Binders)''':固定函数的部分参数 * '''否定器(Negators)''':反转谓词的逻辑 * '''成员函数适配器(Member Function Adapters)''':将成员函数包装为函数对象 == 绑定器(std::bind) == C++11引入的<code>std::bind</code>是最常用的通用绑定器,可以绑定参数、重排参数顺序或设置占位符。 === 基本语法 === <syntaxhighlight lang="cpp"> #include <functional> auto new_callable = std::bind(callable, arg_list); </syntaxhighlight> === 示例1:绑定固定参数 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> void print_sum(int a, int b) { std::cout << a + b << '\n'; } int main() { auto print_plus_10 = std::bind(print_sum, std::placeholders::_1, 10); print_plus_10(5); // 输出15 (5+10) } </syntaxhighlight> === 示例2:重排参数顺序 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> void print_division(float a, float b) { std::cout << a / b << '\n'; } int main() { // 将第二个参数绑定到第一个位置,第一个参数绑定到第二个位置 auto invert_division = std::bind(print_division, std::placeholders::_2, std::placeholders::_1); invert_division(10, 2); // 输出0.2 (2/10) } </syntaxhighlight> == 否定器(std::not_fn) == C++17引入的<code>std::not_fn</code>用于反转谓词的逻辑结果。 === 示例 === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> #include <vector> #include <algorithm> bool is_even(int n) { return n % 2 == 0; } int main() { std::vector<int> v = {1, 2, 3, 4, 5}; // 计算奇数数量 int count = std::count_if(v.begin(), v.end(), std::not_fn(is_even)); std::cout << count; // 输出3 } </syntaxhighlight> == 成员函数适配器 == STL提供了适配器来调用成员函数,包括: * <code>std::mem_fn</code>:将成员函数包装为函数对象 * 过时的<code>std::mem_fun</code>和<code>std::mem_fun_ref</code> === 现代用法(C++11及以上) === <syntaxhighlight lang="cpp"> #include <iostream> #include <functional> #include <vector> #include <algorithm> struct Person { std::string name; int age; void print() const { std::cout << name << " (" << age << ")\n"; } }; int main() { std::vector<Person> people = {{"Alice", 25}, {"Bob", 30}}; // 使用mem_fn调用成员函数 std::for_each(people.begin(), people.end(), std::mem_fn(&Person::print)); } </syntaxhighlight> == 实际应用场景 == === 场景1:回调函数定制 === 在事件处理系统中,可以使用绑定器为不同事件创建特定的回调: <syntaxhighlight lang="cpp"> #include <functional> #include <iostream> class Button { public: using Callback = std::function<void()>; void setCallback(Callback cb) { callback = cb; } void click() { if(callback) callback(); } private: Callback callback; }; void log_message(const std::string& msg, int severity) { std::cout << "[" << severity << "] " << msg << "\n"; } int main() { Button btn; // 绑定特定日志消息和严重级别 btn.setCallback(std::bind(log_message, "Button clicked!", 1)); btn.click(); // 输出: [1] Button clicked! } </syntaxhighlight> === 场景2:算法参数定制 === 在STL算法中使用适配器定制比较行为: <syntaxhighlight lang="cpp"> #include <algorithm> #include <vector> #include <functional> #include <iostream> int main() { std::vector<int> v = {5, 3, 1, 4, 2}; // 使用绑定器创建自定义比较器 auto greater_than = [](int x, int y) { return x > y; }; std::sort(v.begin(), v.end(), std::bind(greater_than, std::placeholders::_2, std::placeholders::_1)); for(int n : v) std::cout << n << ' '; // 输出: 1 2 3 4 5 } </syntaxhighlight> == 性能考虑 == 函数适配器会引入一定的开销: * 额外的间接调用 * 可能的堆分配(对于捕获大量数据的绑定表达式) * 内联机会减少 在性能关键路径中,应考虑直接使用lambda表达式或手写函数对象。 == 现代C++替代方案 == C++11及以后版本中,lambda表达式通常可以替代函数适配器,提供更清晰的语法: === 绑定器替代 === <syntaxhighlight lang="cpp"> // 使用std::bind auto plus_10 = std::bind(std::plus<int>(), std::placeholders::_1, 10); // 使用lambda auto plus_10_lambda = [](int x) { return x + 10; }; </syntaxhighlight> === 成员函数适配器替代 === <syntaxhighlight lang="cpp"> // 使用std::mem_fn std::for_each(people.begin(), people.end(), std::mem_fn(&Person::print)); // 使用lambda std::for_each(people.begin(), people.end(), [](const Person& p) { p.print(); }); </syntaxhighlight> == 总结 == 函数适配器是STL中强大的工具,允许开发者: * 修改现有函数对象的调用方式 * 减少需要编写的样板代码 * 创建更灵活的组件 随着C++的发展,lambda表达式在许多场景下提供了更直观的替代方案,但理解函数适配器仍然很重要,特别是在维护遗留代码或需要与现有STL组件交互时。 <mermaid> graph TD A[函数适配器] --> B[绑定器] A --> C[否定器] A --> D[成员函数适配器] B --> E[std::bind] B --> F[过时的bind1st/bind2nd] C --> G[std::not_fn] C --> H[过时的not1/not2] D --> I[std::mem_fn] D --> J[过时的mem_fun/mem_fun_ref] </mermaid> 函数适配器与相关技术的关系可以用以下公式表示: <math> \text{适配后的函数} = \text{适配器} \circ \text{原始函数} </math> [[Category:编程语言]] [[Category:C++]] [[Category:C++stl 函数对象]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)