运算符重载: 函数调用运算符
2024年1月4日 2024年1月4日
必须作为成员函数
如果为类类型重载了函数调用运算符 ()
, 可以像使用函数一样使用对象: 对其使用调用运算符, 并传入参数, 调用重载的调用运算符
重载了调用运算符的类对象使用起来比函数更灵活, 因为可以使用数据成员来存储状态
如果类定义调用运算符, 则该类的对象也称作函数对象 function object
调用运算符可有多个重载版本
用于打印的函数对象
1class PrintString 2{ 3public: 4 PrintString(ostream &o = cout, char c = ' ') : os(o), sep(c) {} 5 void operator() (const string &s) const { os << s << sep; } 6private: 7 ostream &os; 8 char sep; 9}; 10 11PrintString printer; 12printer(s); 13PrintString errors(cerr, '\n'); 14errors(s);
函数对象常常作为泛型算法的实参
1for_each(vs.begin(), vs.end(), PrintString(cerr, '\n'));
lambda是函数对象
lambda表达式产生的类不含默认构造函数, 赋值运算符和默认析构函数; 是否含有默认的拷贝/移动构造函数视捕获的数据成员类型而定
书上指出lambda表达式为未命名类的未命名对象, 但并未清楚说明lambda表达式的实现
标准库定义的函数对象
模板类
我们惯常使用运算符, 但用作泛型算法的参数, 得给出名称
头文件
1#include <functional>
算术运算
- | |
---|---|
plus<T> | |
minus<Type> | |
multiplies<Type> | |
divides<Type> | |
modulus<T> | 取余 |
negate<T> |
1plus<int> intAdd; 2negate<int> intNegate; 3int sum = intAdd(10, 20); 4sum = intNegate(intAdd(10, 20)); 5sum = intAdd(10, intNegate(10));
关系运算
- | |
---|---|
equal_to<T> | 相等 |
not_equal_to<Type> | |
greater<Type> | |
greater_equal<Type> | |
less<Type> | |
less_equal<Type> |
示例
- 泛型算法: 排序
1sort(svec.begin(), svec.end(), greater<string>()); // 从大到小
- 关联容器: 关键字排序
1vector<string *> nameTable; // nameTable保存string指针 2sort(nameTable.begin(), nameTable.end(), [](string *a, string *b) { return a < b; }); // 使用内置的<会产生未定义行为 3sort(nameTable.begin(), nameTable.end(), less<string *>()); // 标准库的less类对于指针有良好定义,可以比较指针的地址 4 5// 关联容器使用的就是less<KType>对元素排序,所以关联容器保存指针时,元素仍有序
逻辑关系
- | |
---|---|
logical_and<Type> | |
logical_or<Type> | |
logical_not<Type> | 逻辑非 |