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_t
operator()(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都属于可调用对象,使用它们可带来便捷性和高效性。
更多推荐



所有评论(0)