5 Function-like classes
function-like classes, 所谓仿函数
为什么 C++ 要让一个 class 所做出来创建出来的对象, 让这个对象像指针或者像一个函数 ?
我们这里先不去谈这个, 我们这里只谈一下语法
要让它像一个函数, 我们首先得知道函数长什么样子
函数有一个函数名称, 要用一个小括号把它作用上去, 事实上小括号这个操作符就叫做 function call operator, 也就是函数调用操作符
所以任何一个东西如果能够接受小括号这个操作符, 我们就把这个东西叫作函数或者像函数的东西
现在在标准库里面有这么三个东西, 他们都是 class
template <class T>
struct identity
{
const T& operator() (const T& x) const
{
return x;
}
};
template <class Pair>
struct select1st
{
const typename Pair::first_type&operator()(const Pair& x) const
{
return x.first; // 把收到的 Pair, pair 就是一对, 把接收到的这一对, 取出第一个
}
};
template <class Pair>
struct select2nd
{
const typename Pair::second_type&operator()(const Pair& x) const
{
return x.second;
}
};
这三个就是 function-like class, 还是模板
这就是语法的部分, 当然小括号里面具体要做什么, 那就看具体的设计了
这个 identity 意思是视为同一个东西, 它接受 x, 传回来 x. 你给它 x, 它就传 x 给你.
select 1st 是接受一个任意类型, 不过它把名字叫作 Pair, 这是暗示我们要给它一个 Pair.
select1st<Pair>()();
相对应的有 select 2nd
既然这里说了 Pair 这个东西, 那我们来看看标准库里面的 Pair 这个 class
template<class T1, class T2>
struct pair
{
T1 first;
T2 second;
pair() : first(T1()), second(T2())
pair(const T1& a, const T2& b) : first(a), second(b)
{
}
/*...*/
};
这个 pair 的代码是旧版本的, 新版本太复杂了
它里面有两个数据叫 first 和 second, 这两个数据的数据类型随便你指定, 因为它们两个是模板, 它们不需要一样
由于有这 first 和 second, 所以最上面的代码取的时候就是取的 first 和 second
我们回到主题
你只要在 class 里面看到有像这样重载 () 这样的符号, 那么它的用意就是想要变成一个 function
我们就说这一种 class, 所创建出来的对象叫作函数对象 (或者叫仿函数)
其实上面代码是长这样的 :
这里面的灰色部分还很长, 它到底是什么呢, 我们仔细看. 它其实是各自有继承另外的一些 class.
那么这些继承的 class 有什么用呢, 我们往下看
刚刚看到的 unary_function 就是一个操作数的, binary_function 就是两个操作数的.
为什么要继承这两个呢 ? 这个详见 C++ 标准库系列视频.
这里只是让你知道, 原来标准库里面的这些仿函数几乎都长这样, 什么样呢, 就是继承一些奇特的 base classes, 比如 unary_function binary_function
现在提一个问题, unary_function 和 binary_function, 这两个 class 的大小是多少 ?
大小就是把数据加起来, 它们没有数据, 它们只有一些 typedef
, 它们也没有 function, 所以你可能很少写过这种奇怪的 class, 这两个 class 的大小都是 0.
如果你很好奇, 用 sizeof()
去看看它们的大小的话, 你可能得到的是 1. 理论是 0, 但是实际上由于一些限制, 得到的可能是 1.
这里就是想说, 标准库里面有很多的仿函数, 这些仿函数都是一些小小的 class, 它们里面有重载小括号, 重载小括号就说它是一个仿函数了
然后我们这里贴了一些源代码告诉你, 这些仿函数都有继承一些奇怪的父类, 这些父类大小是 0, 也没有函数, 只有一些 typedef
, 继承这些父类有什么用, 这是一个大的话题, 在 C++ 标准库系列的视频里面才会讲.
所以对于一个类, 要像什么呢. 有两个大分类, 一种是像指针, 一种是像函数.