函数对象:重载函数调用操作符operator()的类,其对象常称为函数对象。当用该对象调用此操作符时,其表现形式如同普通函数调用一般,因此取名叫函数对象。(一元函数对象)
template <typename T>
class PrintElement
{
public:
void operator()(T &t)
{
cout << t << " ";
}
};
main()
{
int a = 10;
PrintElement<int>(a);//函数对象
}
函数对象和普通函数
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
拿for_each为例,这里需要传入三个参数,迭代器首元素位置、迭代器尾元素位置、函数对象(值,非引用)。当传入函数对象时就要区别是函数对象和普通函数的区别。
函数对象是属于类对象,能突破函数的概念,能保持调用状态信息。
/*
template<class _InIt,
class _Fn> inline
_Fn for_each(_InIt _First, _InIt _Last, _Fn _Func)
{ // perform function for each element [_First, _Last)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst)
{
_Func(*_UFirst);
}
return (_Func);
}
*/
分析for_each源码可以发现,有三个参数(迭代器首元素位置,迭代器尾元素位置,函数对象(值,非引用)),返回值是一个函数对象。
在这里函数参数传递的是一个值而非引用。
返回值是一个函数对象自身
template <typename T>
class PrintElement
{
public:
PrintElement()
{
m_num = 0;
}
void operator()(T &t)
{
m_num++;
cout << t << " ";
}
void PrintNum()
{
cout <<"调用次数:"<< m_num << endl;
}
private:
int m_num;
};
//函数模板
template<typename T>
void PrintElement1(T &t)
{
cout << t << " ";
}
//普通函数
void PrintElement2(int &t)
{
cout << t << " ";
}
void Fun1()
{
int a = 10;
PrintElement<int> ();
//printElement(a);//函数对象()的执行 很像一个函数//仿函数
PrintElement1<int>(a);
PrintElement2(a);
}
void Fun2()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
PrintElement<int> printElement;
//传入函数对象
for_each(v1.begin(), v1.end(), printElement);
cout << endl;
//传入普通函数
for_each(v1.begin(), v1.end(), PrintElement2);
//判断是值传递还是引用传递
for_each(v1.begin(), v1.end(), printElement);
printElement.PrintNum();
//for_each的返回值是一个函数对象
printElement = for_each(v1.begin(), v1.end(), printElement);
printElement.PrintNum();
}