C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象(二)

2014-11-24 12:36:41 · 作者: · 浏览: 2
元操作符定义的调用操作符需要两个给定类型的形参,而一元函数对象类型定义了接受一个实参的调用操作符。


2、表示操作数类型的模板类型

每个函数对象类都是一个类模板,我们需要为该模板提供一个类型:

    plus
  
    strAdd;
    plus
   
     intAdd; 
   
  


应用:

    plus
  
    strAdd;
    cout << strAdd("Hello ","World\n");

    plus
   
     intAdd; negate
    
      intNegate; cout << intAdd(10,20) << endl; int sum = intAdd(10,intNegate(20)); cout << sum << endl; 
    
   
  

3、在算法中使用标准库函数对象

函数对象常用于覆盖算法使用的默认操作符。例如,sort默认使用operator<按升序对容器进行排序。为了按降序对容器进行排序,可以传递函数对象greater。该类将产生一个调用操作符,调用基础对象的大于操作符。

    sort(strVec.begin(),strVec.end(),greater
  
   ());  //降序排序

  

//附:完整程序测试
void printVec(const vector
  
    &vec)
{
    for (vector
   
    ::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) { cout << *iter << '\t'; } cout << endl; } int main() { ifstream inFile("input"); vector
    
      strVec; string word; while (inFile >> word) { strVec.push_back(word); } sort(strVec.begin(),strVec.end()); //升序排序 printVec(strVec); sort(strVec.begin(),strVec.end(),greater
     
      ()); //降序排序 printVec(strVec); } 
     
    
   
  

第二个sort函数的第三个实参greater 是一个临时对象,是 一个将 > 操作符应用于两个 string 操作数的函数对象


三、函数对象的函数适配器

标准库提供了一组函数适配器,用于特化和扩展一元和二元函数对象。函数适配器分为:

1、绑定器:是一种函数适配器,它通过将一个操作数绑定到给定值,而将二元函数对象转换为一元函数对象。有:bind1str,bind2nd.

每个绑定器接受一个函数对象和一个值,bind1st给定值绑定到二元函数对象的第一个实参,bind2nd将给定值绑定到二元函数对象的第二个实参

    //计算容器中所有小于或等于 10 的元素的个数
    count_if(vec.begin(),vec.end(),bind2nd(less_equal
  
   (),10));
  

该适配器返回一个函数对象,该对象用10作右操作数应用<=操作符,调用计算输入范围中小于或等于10的元素的个数。


2、求反器:将谓词函数的真值求反。有:not1和not2。

not1将一元函数对象的真值求反,not2将二元函数对象的真值求反。

    //是对不 <= 10[即:> 10] 的那些元素进行计数
    count_if(vec.begin(),vec.end(),
             not1(bind2nd(less_equal
  
   (),10)));

  

//P453 习题14.37
//(a)
int main()
{
    vector
  
    ivec;

    ifstream inFile("input");
    int val;

    while (inFile >> val)
    {
        ivec.push_back(val);
    }

    typedef vector
   
    ::iterator iterType; iterType iter = ivec.begin(); while ((iter = find_if(iter,ivec.end(),bind2nd(greater
    
     (),10))) != ivec.end()) { cout << *iter << endl; ++ iter; } } 
    
   
  


//(b)
int main()
{
    vector
  
    strVec;

    ifstream inFile("input");
    string val;

    while (inFile >> val)
    {
        strVec.push_back(val);
    }

    typedef vector
   
    ::iterator iterType; iterType iter = strVec.begin(); //主要的改动在于是换成了not_equal_to while ((iter = find_if(iter,strVec.end(), bind2nd(not_equal_to
    
     (),"pooh"))) != strVec.end()) { cout << *iter << endl; ++ iter; } } 
    
   
  


//(3)
int main()
{
    vector
  
    ivec;

    ifstream inFile("input");
    int val;

    while (inFile >> val)
    {
        ivec.push_back(val);
    }


    typedef vector
   
    ::iterator iterType; multiplies
    
      intMulti; for (iterType iter = ivec.begin(); iter != ivec.end(); ++iter) { *iter = intMulti(*iter,2); } /**或者使用标准库算法:transform *transform(ivec.begin(),ivec.end(),ivec.begin(),bind2nd(multiplies
     
      (),2)); */ for (iterType iter = ivec.begin(); iter != ivec.end(); ++iter) { cout << *iter << endl; } } 
     
    
   
  

//习题14.39
int main()
{
    ifstream inFile("input");
    vector
  
    words;
    string word;

    while (inFile >> word)
    {
        words.push_back(word);
    }

    cout << "And " << count_if(words.begin(),words.end(),GT_cls(3))
         << " words`s size is equal to 3 or longer" << endl;

    greater_equal
   
     sizeGreEQ; string::size_type wc = 0; for (vector
    
     ::iterator iter = words.begin(); iter != words.end(); ++iter) { if (sizeGreEQ(iter -> size(),3)) ++ wc; } cout << "And " << wc << " words`s size is equal to 3 or longer" << endl; }