函數對象:重載函數調用操作符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();
}