26-函数对象
16.5 函数对象
很多STL算法都使用函数对象——也叫函数符(functor)。函数符是可以以函数方式与()结合使用的任意对象。这包括函数名、指向函数的指针和重载了()运算符的类对象(即定义了函数operator()()的类)。例如,可以像这样定义一个类:
class Linear
{
private:
double slope;
double y0;
public:
Linear(double sl_ = 1, double y_ = 0)
: slope(sl_), y0(y_) {}
double operator()(double x) {return y0 + slope * x; }
};
这样,重载的()运算符将使得能够像函数那样使用Linear对象:
Linear f1;
Linear f2(2.5, 10.0);
double y1 = f1(12.5); // right-hand side is f1.operator()(12.5)
double y2 = f2(0.4);
其中y1将使用表达式0 + 1 12.5来计算,y2将使用表达式10.0 + 2.5 0.4来计算。在表达式y0 + slope * x中,y0和slope的值来自对象的构造函数,而x的值来自operator() ()的参数。
还记得函数for_each吗?它将指定的函数用于区间中的每个成员:
for_each(books.begin(), books.end(), ShowReview);
通常,第3个参数可以是常规函数,也可以是函数符。实际上,这提出了一个问题:如何声明第3个参数呢?不能把它声明为函数指针,因为函数指针指定了参数类型。由于容器可以包含任意类型,所以预先无法知道应使用哪种参数类型。STL通过使用模板解决了这个问题。for_each的原型看上去就像这样:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
ShowReview()的原型如下:
void ShowReview(const Review &);
这样,标识符ShowReview的类型将为void(*)(const Review &),这也是赋给模板参数Function的类型。对于不同的函数调用,Function参数可以表示具有重载的()运算符的类类型。最终,for_each()代码将具有一个使用f()的表达式。在ShowReview()示例中,f是指向函数的指针,而f()调用该函数。如果最后的for_each()参数是一个对象,则f()将是调用其重载的()运算符的对象。