前言
本小节将介绍STL六大组件之一的仿函数(又称函数对象),在前面分析算法部分时,我们其实已经见识到了仿函数的大量使用(各算法的另一个版本,传入comp仿函数)。关于仿函数的实现,其实就是重载了()
运算符,然后调用,所以又称函数对象。接下来我们就来分析该部分。
仿函数
虽然函数指针也可以完成将各种操作当作参数传入,但是之所以出现了仿函数,是因为函数指针并不能满足STL对抽象的要求,也不能和其他组件很好的搭配。
SGISTL
自带了一部分仿函数,都在stl_function.h
中,如果要使用仿函数,则需要引入头文件functional
。这里给出一个简单的例子:
#include <iostream>
#include <functional>
using namespace std;
int main()
{
int i = 2, j = 8;
multiplies<int> mul;
cout << mul(i, j) << endl; //调用()操作符
cout << minus<int>()(i, j) << endl; //产生一个临时无名对象调用()操作符
return 0;
}
上面使用的两个仿函数的源码实现如下:
//可见就只是重载了()操作符
//不过它们都继承了binary_function
//这个基类的作用我们等下分析
template <class T>
struct minus : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x - y; }
};
template <class T>
struct multiplies : public binary_function<T, T, T> {
T operator()(const T& x, const T& y) const { return x * y; }
};
STL
的仿函数按照操作数的个数分类分为一元和二元仿函数;按照功能来分类,可以分为算术运算、关系运算、逻辑运算三类。上面的这个例子中,继承的binary_function
其实是代表该运算是二元运算,并且接着的三个模板参数分别代表两个参数的类型以及返回值的类型,这样做的目的都是为了可被函数配接器配接。
一元仿函数和二元仿函数的基类
//一元仿函数的基类
template <class Arg, class Result>
struct unary_function {
//声明了参数以及返回值类型的别名
typedef Arg argument_type;
typedef Result result_type;
};
//二元仿函数的基类
template <class Arg1, class Arg2, class Result>
struct binary_function {
//声明了参数以及返回值类型的别名
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
与配接器的联系
而配接器就可以利用定义的这些相应型别完成和其仿函数不同