C++运算符重载——函数调用运算符 ()
函数调用运算符为 (),放在函数名后边提供实参列表,实现函数调用。如果 C++ 的 class、struct 重载了函数调用运算符,那么可以像使用函数一样使用它们的对象,即可以 “调用” 这些对象。调用对象实际是在执行重载函数调用运算符(函数)。
如果类定义了函数调用运算符,则该类的对象称为函数对象或可调用对象。这些函数对象常用于泛型算法、哈希函数。
一、函数调用运算符重载语法
返回值类型 operator()(param list) 函数修饰符 {函数体}
// 1. 摘自 <<C++ primer>>
struct absInt {int operator()(int val) const {return val < 0 ? -val : val;}
};// 2. 摘自 /usr/include/c++/9/bits/functional_hash.h
// Primary class template hash.template<typename _Tp>struct hash;/// Specialization for float.
template<>
struct hash<float> : public __hash_base<size_t, float>
{size_toperator()(float __val) const noexcept {// 0 and -0 both hash to zero.return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0;}
};
与其他类一样,函数对象类也可以包含其他成员,生成包含状态的函数对象类:
// 摘自 <<C++ primer>>
class PrintString
{
public:PrintString(ostream &o = cout, char c = ' ') : os(o), sep(c) {}void operator()(const string &s) {os << s << sep;}private:ostream &os;char sep;
};
函数对象常常用于泛型算法的实参来提高性能,比如 for_each 算法:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>class PrintString
{
public:PrintString(std::ostream &o = std::cout, char c = ' ') : os(o), sep(c) {}void operator()(const std::string &s) {os << s << sep;}private:std::ostream &os;char sep;
};int main(int argc, char *argv[]) {std::vector<std::string> vs = {"123", "456", "789", "abc"};// 第三个参数是一个函数对象类(PrintString)的临时对象std::for_each(vs.begin(), vs.end(), PrintString(std::cout, '\n'));}// for_each 可能的实现
template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{for (; first != last; ++first) {f(*first);}return f; // C++11 起隐式移动
}
二、总结
函数对象含有不仅于此还包括 lambda,使用它们可带来便捷性和高效性。