注意:这是一篇从旧博客恢复的文章。
原地址:http://freemeepo.com/blog/archives/95
注:有更新
(只讨论在G++中的实现情况)
在G++中,max是用函数实现的。头文件中定义如下:
template<typename _Tp>
inline const _Tp&
max(const _Tp& __a, const _Tp& __b)
{
// concept requirements
__glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
//return __a < __b ? __b : __a;
if (__a < __b)
return __b;
return __a;
}
而没有使用宏的方式(类似于#define max(a,b) (((a) < (b)) ? (b) : (a))
这样的定义)。
UPDATE: 事实上,使用宏来定义max是非常危险的。
它使用的是template,这样实现了不管什么类型都可以执行这个函数。不过需要注意的是,template用于普通函数可以直接这样做,但用于类时,在使用时则需加尖括号显式声明类型,例如vector<int> v;
而greater函数的实现,则不太一样了。
先说一下greater函数的用法。例如我们在sort的时候,这样使用sort(v.begin(),v.end(),greater<int>());
则可以对int型的vector进行降序排序。经过思考后发现,这样函数的用法跟其他函数好像不大一样,比如为什么在最后要加个括号呢?
其实,这个函数并非真正的函数,而是叫做仿函数的一个东西,它是用一个类实现的,并在其中重载了括号运算符,使它用起来像个函数而已。G++中是这样实现的:
template<typename _Tp>
struct greater : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x > __y; }
};
于是我们可以这样调用这个函数greater<int>()(3,5)
,结果为0。这样还有两个问题:
1、为何要用尖括号指定类型?
这是因为template对类使用必须指定类型。
2、传参前为何需要加一对空括号呢?
这是因为它其实是调用了一个默认构造函数。因为它的本质还是一个类型,需要构造一个变量是这个类型,然后调用这个变量的()运算符。用加括号的方法就相当于构造了一个变量,这种方法与vector<int>()
和point(3,5)
其实本质上是一样的,只是一个是调用默认构造函数,一个是带两个参数的构造函数。
其实greater这样使用也是可以的:
vector<int> v;
/*------*/
greater<int> g;
sort(v.begin(),v.end(),g);
另外,要想用仿函数作为某个函数的参数传入的话,就必须用template,因为仿函数确实不是函数,在参数定义上很麻烦,所以template很好地解决了这个问题。
Comments
注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。