如果类重载了函数调用运算符,则我们可以像使用函数一样使用该类的对象。因为这样的类同时也能储存状态,所以与普通的函数相比它们更加灵活。
class absInt { public: int operator()(int val) const { return (val < 0)?-val : val; } }; int main() { int i = -42; absInt absObj; int ui = absObj(i); cout << ui << endl; }
即使absObj只是一个对象而非函数,我们也能“调用”该对象。调用对象实际上是在运行重载的调用运算符。在此例中,该运算符接受一个int值并返回其绝对值。
如果类定义了调用运算符,则该类的对象称作函数对象(function object)。因为可以调用这种对象,
含有状态的函数对象类
和其它类一样,函数对象除了operator()之外也可以包含其它成员。函数对象类通常含有一些数据成员,这些成员被用于定制调用运算符中的操作。
class printString { public: printString(ostream &o = cout, char c = ' ') : os(o), sep(c) {} void operator()(const string &s) const {os << s << sep;} private: ostream &os; char sep; }; int main() { printString printer; printer(s); printString errors(cerr, '\n'); errors(s); }
函数对象常常作为泛型算法的实参。例如,可以使用标准库for_each算法和我们自己的printString类来打印容器的内容:
for_each(vs.begin(), vs.end(), printString(cerr, '\n'));
for_each的第三个实参是类型printString的一个临时对象,其中我们用cerr和换行符初始化了该对象。当程序调用for_each时,将会把vs中的每个元素依次打印到cerr中,元素之间以换行符分割。