当前位置:C++技术网 > 资讯 > C++函数对象的剖析及详细实例

C++函数对象的剖析及详细实例

更新时间:2016-04-27 18:12:07浏览次数:1+次

一个函数对象,即一个重载了括号操作符"()"的对象。(对于这里,我是这么理解的,所谓的函数对象并不仅仅就是指重载括号操作符"()"的对象,在这里的"()"是指没有参数的,但是,在泛型编程中,很多的函数源码都是有参数的operator)当用该对象调用此操作符时,其表现形式如同普通函数调用一般,因此取名叫函数对象。具体的例子,我在《STL中的函数符——operator重载操作符》中写了代码,在这里我再次搬过来:
#include "iostream"
#include "windows.h"

class Function
{
int y;
public:
Function(int x): y(x){};

public:
double operator()(double x) 
{  
return x+2*y;
} 

};

int main()
{
using namespace std;

Function myFunc(1);

cout<<myFunc(2.0)<<endl;

system("pause");
}
我们定义了一个function类的对象myFunc,并传入一个参数,而后程序会自动为我们调用Function类中的operator()(//传入一个参数)。
其实,在刚刚接触operator()操作符的时候,我很不理解C++为什么要引入这个概念,直到,我看到了部分的STL源码,原来,在STL中的大多数函数的源码实现,都是基于这个operator()的。因此,我就知道了这个operator()的重要性!作为一个要成为C++工程师的我来说,这个是必须要理解掌握的。
下面,我们来看一段代码:
#include "iostream"
#include "list"
#include "iterator"
#include "algorithm"

using namespace std;

template<class T>
class TooBig
{
private:
T cutoff;
public:
TooBig(const T & t): cutoff(t){}

bool operator()(const T & v){
return v > cutoff;
}
};

void outint(int n){std::cout<<n<<" ";}

int main()
{
TooBig<int> f100(100);
int vals[10]={50,100,90,180,60,120,415,88,188,201};
list<int>yadayada(vals,vals+10);
list<int>etc(vals,vals+10);
cout<<"原始的list:"<<endl;
for_each(yadayada.begin(),yadayada.end(),outint);
cout<<endl;
for_each(etc.begin(),etc.end(),outint);
cout<<endl;

yadayada.remove_if(f100);

TooBig<int> f200(200);
etc.remove_if(f200);
cout<<"改变之后的list:"<<endl;
for_each(yadayada.begin(),yadayada.end(),outint);
cout<<endl;

for_each(etc.begin(),etc.end(),outint);
cout<<endl;

system("pause");
return 0;
}
然后看看实现:

for_each函数中outint函数并没有带参数,因为for_each函数的前两个参数指定了一个range,在该range中的数据元素,都作为了outint的参数。我想,这句代码,你可以改成for语句,我就不写了。相信你懂了。
yadayada.remove_if(f100);
数据结构list的数据元素作为remove_if的range,并依次传给f100作为参数。然后在TooBig中,调用operator函数。TooBig类的对象实例f100先是调用构造函数实例化。而后在传入参数的话,就作为函数对象做出类似函数的行为,调用类中的operator()。其实要说详细的话,应该这么分析:
template <class T>
bool tooBig(const T& val, const T& lim)
{
return val>lim;
}
然后,我们将其转化为单个参数的函数对象:
template<class T>
class TooBig2
{
private:
T cutoff;
public:
TooBig2(const T& t):cutoff(t){}
bool operator()(const T& v)
{
return tooBig<T>(v,cutoff);
}
}
因此原来的代码就可以这么理解:
TooBig2<int> tb100(100);
int x;
cin>>x;
if(tb100(x))//就像是调用tooBig(x,100)一样
{
....
}
而类TooBig2就相当于一个函数适配器。