函数对象就是一个实现了operator()的类。
正是因为实现了operator()操作符,所以在使用的时候,可以调用 ()操作符,看起来就像是对一个函数的调用,但是实际上这是一个对象。所以称之为函数对象。
普通函数 vs 函数对象类
//普通函数
void WhoMakesMeAngry(string name)
{
std::cout << name << "made me angry" << std::endl;
}
//函数对象类
class FunctionObjectDefine
{
public:
void operator()(string name) { std::cout << name << "made me angry" << std::endl;};
};
int main()
{
WhoMakesMeAngry("taz")
FunctionObjectDefine func;
func("taz")//和普通函数 WhoMakesMeAngry("taz")调用方式一样
return 0;
}
上述这个例子中,函数对象并没有存内部状态,即没有数据成员,那用直接用函数好了呀。
函数对象的特殊作用就是可以实现携带附加数据,而普通函数不行。
函数对象在STL中作为参数使用
1.std::generate_n 中的 Generator生成器
template <class OutputIterator, class Size, class Generator>
void generate_n ( OutputIterator first, Size n, Generator gen )
{
while (n>0) {
*first = gen();
++first; --n;
}
}
其中第三个参数 Generateor,传入的就是一个函数对象或者是函数指针,类型是无参数的输入,返回是符合*first类型的值。下面例子分别用函数对象和函数指针来作为参数传入:
//储存了内部状态的函数对象 m_origin
class SuccessiveNumFunObject
{
public:
SuccessiveNumFunObject(int origin = 0):m_origin(origin){}
int operator() ()
{
return m_origin++;
}
private:
int m_origin;
};
//普通函数,对全局函数的操作
int current = 3;
int SuccessiveNumFun () { return current++; }
vector<int> dest;
// 传入的参数是实例化的函数对象(3给函数对象的内部状态赋初值)
generate_n(back_inserter(dest),10,SuccessiveNumFunObject(3));
// 传入的参数是函数指针(函数名就可以表示函数指针)
// generate_n(back_inserter(dest),10,SuccessiveNumFun);
2.std::find_if 中的UnaryPredicate一元谓词函数
template<class InputIterator, class UnaryPredicate> InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred) { while (first!=last) { if (pred(*first)) return first; ++first; } return last; }
同样,第三个参数需要传入函数对象或函数指针,从实现中可以看出,需要的是一个输入参数-*first类型,返回的是bool值。
下面的例子中,没有用到输入的参数。
// 函数对象类
class NthFunObject
{
public:
NthFunObject(int n=0):m_nth(n),m_count(1){}
bool operator() (int)
{
return m_count++ == m_nth;
}
int GetCount()const
{
return m_count;
}
private:
int m_nth;
int m_count;
};
NthFunObject nth(3);
//dest内容为连续数字:3,4,5,6,……,12
vector<int>::iterator nthItr = find_if(dest.begin(),dest.end(),nth);
std::cout << "The 3rd value of dest is " << *nthItr << '\n';
// 函数指针
int gNth = 3;
int gCount = 1;
bool NthFun (int i) {
return (gNth==gCount++);
}
nthItr = std::find_if (dest.begin(), dest.end(), NthFun);
std::cout << "The 3rd value of dest is " << *nthItr << '\n';
类似的,remove_if第三个参数也是一元谓词函数。remove_if 所谓的remove只是概念上的remove:
1,2,3,4,5,6,7,8,9,10 ----> remove_if 为3 ---->1,2,4,5,6,7,8,9,10,10.
算法库绝不改变容器的大小!
3.std::each
template<class InputIterator, class Function> Function for_each(InputIterator first, InputIterator last, Function fn) { while (first!=last) { fn (*first); ++first; } return fn; // or, since C++11: return move(fn); }
需要的是一个输入参数-*first类型,返回类型无所谓。for_each就是对每个元素进行一些操作。
void myfunction (int i) { // function:
std::cout << ' ' << i;
}
struct myclass { // function object type:
void operator() (int i) {std::cout << ' ' << i;}
} myobject;
std::cout << "dest contains:";
for_each (dest.begin(), dest.end(), myfunction);
std::cout << '\n';
// or:
std::cout << "dest contains:";
for_each (dest.begin(), dest.end(), myobject);
std::cout << '\n';
STL中的一些函数对象
modulus<T>
取模函数对象
template <class T> struct modulus : binary_function <T,T,T> {
T operator() (const T& x, const T& y) const {return x%y;}
};
greater<T>
比较第一个参数是否大于第二个参数
template <class T> struct greater : binary_function <T,T,bool> { bool operator() (const T& x, const T& y) const {return x>y;} }; // 降序排列 50 40 30 20 10 int numbers[]={20,40,50,10,30}; std::sort (numbers, numbers+5, std::greater<int>());
less<T>
比较第一个参数是否小于第二个参数
template <class T> struct less : binary_function <T,T,bool> { bool operator() (const T& x, const T& y) const {return x<y;} }
logical_and<T>
逻辑与函数对象
template <class T> struct logical_and : binary_function <T,T,bool> { bool operator() (const T& x, const T& y) const {return x&&y;} };