标准库: function类
2024年1月4日 2024年1月4日
C++中的可调用对象:
- 函数
- 函数指针
- bind创建的对象
- 重载了函数调用运算符的类
- lambda表达式
可调用对象具有类型:
类型 | |
---|---|
lambda表达式 | 未命名类类型 |
函数和函数指针 | 返回值和实参类型决定 |
函数 | 函数类型 |
函数指针 | 函数指针类型 |
重载了函数调用运算符的类 | 类类型 |
bind创建的对象 |
调用形式
call signature
不同类型的可调用对象可以共享同一种调用形式, 调用形式由返回类型和形参列表决定
如:
int(int, int)
支持该调用形式的可调用对象如:
- 函数
- lambda表达式
- 重载了函数调用运算符的类
1int add(int i, int j) { return i + j; } 2 3auto mod = [](int i, int j) { return i % j; }; 4 5struct divide 6{ 7 int operator() (int denominator, int divisor) 8 { 9 return denominator / divisor; 10 } 11};
存放函数指针的函数表
function table
使用关联容器map存储指向函数的指针, 当程序需要执行某个特定操作时, 从表中查找该调用的函数
构建从运算符到函数指针的映射
1int add(int i, int j) { return i + j; } 2 3auto mod = [](int i, int j) { return i % j; }; 4 5map<string, int(*)(int, int)> binops; 6 7binops.insert({"+", add}); 8 9binops.insert({"%", mod}); // 错误:mod类型为类类型
function类
模板类
function对象可以存储给定调用形式的可调用对象, 对可调用对象进行了统一
头文件
1#include <functional>
初始化
- 默认初始化
1function<T> f;
- 显式构造空function
1function<T> f(nullptr);
- 使用可调用对象初始化function
1function<T> f(obj);
示例
1function<int(int, int)> f1 = add; // 函数名 2function<int(int, int)> f2 = divide(); // divide类的对象 3function<int(int, int)> f3 = [](int i, int j) { return i % j; }; // lambda表达式 4 5cout << f1(4, 2) << endl; 6cout << f2(4, 2) << endl; 7cout << f3(4, 2) << endl;
条件判断
f有可调用对象为真; 假
1f;
调用
使用参数args调用f中的对象
1f(args);
类型成员
- | |
---|---|
result_type | 可调用对象的返回类型 |
argument_type | 可调用对象只有一个实参: 实参类型 |
first_argument_type | 可调用对象有两个实参: 第一个实参类型 |
second_arugment_type | 可调用对象有两个实参: 第二个实参类型 |
存放function对象的函数表
1map<string, function<int(int, int)>> binops = { 2 {"+", add}, // 函数名 3 {"-", minus<int>()}, // 标准库函数对象 4 {"/", divide()}, // 自定义函数对象 5 {"*", [](int i, int j) { return i * j; }}, // lambda表达式 6 {"%", mod} // lambda对象 7}; 8 9binops["+"](10, 5); 10 11// 通过关键字调用可调用对象
function与重载函数
如果有对函数进行重载, 因为二义性的问题, function对象存储函数指针而非函数名
- 二义性
1int add(int i, int j) { return i + j; } 2Sales_data add(const Sales_data&, const Sales_data&); 3map<string, function<int(int, int)>> binops; 4binops.insert({"+", add}); // 存在二义性问题
- 使用函数指针
1int (*fp)(int, int) = add; 2binops.insert({"+", fp});
也可以使用lambda表达式, 在lambda函数体中调用目标函数
1binops.insert({"+", [](int i, int j) { return add(i, j); }});