可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载函数调用操作符;
函数调用操作符必须声明为函数成员。一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别;
定义了调用操作符的类,其对象常称为为函数对象(function object)即它们是行为类似函数的对象;
eg.
struct absInit
{
int operator() (int val)
{
return val <0 ? -val: val;
}
};
struct funcObejct
{
int operator() (int val1,int val2,int val3)
{
return val1 ? val2:val3;
}
};
//test code
int main()
{
int i = -3;
absInit absTest;
std::cout<<"abs of "<<i<<" is "<<absTest(i)<<std::endl;
// test funcObject
funcObejct fun;
std::cout<<fun(-1,2,3)<<std::endl;
std::cout<<fun(10,2,3)<<std::endl;
std::cout<<fun(0,2,3)<<std::endl;
return 0;
}
函数对象经常用作通用算法的实参,通过将算法中需要的Predicate 定义为函数对象可以获得更高的灵活性:
bool GT6(const std::string &s)
{
return s.size() >6;
}
class GT_cls
{
public:
GT_cls(std::size_t val = 0):bound(val) {}
bool operator() (const std::string & s) { return s.size() >= bound;}
private:
std::string::size_type bound;
};
//test code
int main()
{
std::vector<std::string> words;
std::string word;
while(std::cin>>word)
{
words.push_back(word);
}
std::vector<std::string>::size_type wc = std::count_if(words.begin(),words.end(),GT6);
std::cout<<wc<<std::endl;
std::vector<std::string>::size_type wc1 = std::count_if(words.begin(),words.end(),GT_cls(6));
std::cout<<wc1<<std::endl;
std::vector<std::string>::size_type wc2 = std::count_if(words.begin(),words.end(),GT_cls(2));
std::cout<<wc2<<std::endl;
return 0;
}
标准库定义了一组算术,关系与逻辑运算的函数对象类,以及一组函数适配器,都是在functional 头文件中定义的;
具体请参考:http://en.cppreference.com/w/cpp/header/functional
在算犯中使用函数对象,用于覆盖算法使用的默认操作符;
标准库提供两种函数适配器:
1. binder,将一个操作数绑定给给定值而将二元函数对象转换为一元函数对象;
bind1st:将给定值绑定到函数对象的第一个实参;
bind2nd:将给定值绑定到函数对象的第二个实参;
2. negator ,将谓词函数对象的真值求反;
not1:将一元函数对象的真值求反;
not2:将二元函数对象的真值求反;
//test code
int main()
{
std::vector<int> ivec;
ivec.reserve(1030);
for(int i = 0 ; i <1030 ;++i)
{
ivec.push_back(i);
}
//find all value that is greater than 1024
std::vector<int>::iterator result = std::find_if(ivec.begin() , ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
while(result != ivec.end())
{
std::cout<<*result<<std::endl;
result = std::find_if( ++result , ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
}
std::vector<std::string> svec;
svec.push_back("hello world");
svec.push_back("test");
svec.push_back("huqijun");
svec.push_back("pooh");
//find all value that is not equal to "pooh"
std::vector<std::string>::iterator ret = std::find_if(svec.begin(),svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
while(ret != svec.end())
{
std::cout<<*ret<<std::endl;
ret = std::find_if(++ret,svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
}
//double every value
std::vector<int> ivec2;
ivec2.reserve(12);
for(int i = 0; i<12 ; ++i)
{
ivec2.push_back(i);
}
std::for_each(ivec2.begin(),ivec2.end(),std::bind2nd(std::multiplies<int>(),2) );
for(std::vector<int>::iterator i = ivec2.begin() ; i!= ivec2.end() ; ++i)
{
std::cout<<*i<<std::endl;
}
return 0;
}