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

2014-11-24 12:36:41 · 作者: · 浏览: 1

重载操作符与转换

--调用操作符和函数对象

引言:

可以为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符!

struct absInt
{
    int operator() (int val)
    {
        return val > 0   val : -val;
    }
};

通过为类类型的对象提供一个实参表而使用调用操作符,所用的方式看起来系那个一个函数调用:

    absInt absObj;
    int i = -1;
    cout << absObj(i) << endl;

尽管absObj是一个对象而不是函数,我们仍然可以“调用”该对象,效果是运行有absObj对象定义的重载调用操作符,该操作接受一个int值并返回它的绝对值。

函数调用操作符必须声明为成员函数,一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别

定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象!

//P450 习题14.31
struct ifElse
{
    int operator() (int x,int y,int z)
    {
        return x   y : z;
    }
};

int main()
{
    ifElse ifObj;
    cout << ifObj(0,1,2) << endl;
    cout << ifObj(1,1,2) << endl;
}

一、将函数对象用于标准库算法

函数对象经常用作通用算法的实参。回忆曾经的一段程序:

bool GT6(const string &str)
{
    return str.size() > 6;
}


使用GT6作为传给count_if算法的实参,以计算使GT6返回true的单词数目:

    vector
  
   ::size_type wc =
        count_if(words.begin(),words.end(),GT6);

  

1、函数对象可以比函数更灵活

通过将GT6定义为带函数调用成员的类,可以使得传递的string与我们想要的长度进行测试,这样,可以使用同一段代码对不同长度的字符串进行计数:

class GT_cls
{
public:
    GT_cls(size_t val = 0):bound(val){}

    bool operator() (const string &str)
    {
        return str.size() >= bound;
    }

private:
    std::string::size_type bound;
};

2、使用GT_cls函数对象

    cout << count_if(words.begin(),words.end(),GT_cls(6))
         << " words 6 characters or longer" << endl;

这个count_if调用传递一个GT_cls类型的临时对象而不再是名为GT6的函数。用整型值6来初始化那个临时对象,构造函数将这个值存储在bound成员中。现在,count_if每次调用它的函数形参时,它都使用GT_cls的调用操作符,该调用操作符根据bound的值测试其string实参的长度。

使用函数对象,容易修改程序以根据其他值进行测试,只需为传给count_if的对象改变构造函数实参即可。

    //计算长度在5个字符以上的单词数
    cout << count_if(words.begin(),words.end(),GT_cls(5))
         << " words 6 characters or longer" << endl;  

还可以用来计算长度在1到10个字符的单词数:

    for (size_t i = 1; i != 11; ++i)
    {
        cout << count_if(words.begin(),words.end(),GT_cls(i))
             << " words " << i << " characters or longer" << endl;
    }

如果使用函数替代函数对象来编写这个程序,可能需要编写10个(⊙ ⊙b汗)不同的函数,每个函数测试一个不同的值!

//P451 习题14.33
class GT_cls
{
public:
    GT_cls(size_t val = 0):bound(val) {}

    bool operator() (const string &str)
    {
        return str.size() > bound;  //将>=改为>
    }

private:
    std::string::size_type bound;
};

int main()
{
    vector
  
    words;
    ifstream inFile("input");
    string word;
    while (inFile >> word)
    {
        words.push_back(word);
    }

    vector
   
    ::iterator findIter = find_if(words.begin(),words.end(),GT_cls(5)); if(findIter != words.end()) { cout << *findIter << endl; } else { cout << "Have No Found!" << endl; } } 
   
  

//习题14.34
struct IsSame
{
    bool operator() (const string &s1,const string &s2)
    {
        return s1 == s2;
    }
};

int main()
{
    IsSame isSame;
    cout << isSame("xiao","fang") << endl;
    cout << isSame("Ha","Ha") << endl;
}

//习题14.35/36
class BET_cls
{
public:
    BET_cls(size_t Max = 0,size_t Min = 0):max(Max),min(Min) {}
    bool operator() (const string &str)
    {
        return str.size() <= max && str.size() >= min;
    }

private:
    std::string::size_type max;
    std::string::size_type min;
};

class GT_cls
{
public:
    GT_cls(size_t size = 0):bound(size) {}
    bool operator() (const string &str)
    {
        return str.size() >= bound;
    }

private:
    std::string::size_type bound;
};
int main()
{
    ifstream inFile("input");
    vector
  
    words;
    string word;

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

    cout << "The is " << count_if(words.begin(),words.end(),BET_cls(9,1))
         << " words`s size is between 1 and 9" << endl;

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

  


二、标准库定义的函数对象

标准库定义了一组算术、关系与逻辑函数对象类。标准库还定义了一组函数适配器,使我们能够特化或者扩展标准库所定义的以及自定义的函数对象类。这些标准库函数对象类型是在functional头文件中定义的。

标准库函数对象

类型

函数对象

所应用的操作符

算术函数对象类型

plus

+

minus

-

multiplies

*

divides

/

modulus

%

关系函数对象类型

negate

-

equal_to

==

not_equal_to

!=

greater

>

greater_equal

>=

less

<

less_equal

<=

逻辑函数对象类型

logical_and

&&

logical_or

||

logical_not

!



1、每个类表示一个给定操作符

每个标准库函数对象类表示一个操作符,即每个类都定义了应用命名操作的调用操作符。如plus是表示加法操作符的模板类型,plus模板中的调用操作符对一对操作数使用+运算!

//假设Type类型为int,简单实现一下plus
class Plus
{
public:
    int operator() (int a,int b)
    {
        return a + b;
    }
//...
};

有两个一元函数对象类:一元减(negate ))和逻辑非(logical_not ))。其余的标准库函数对象都是表示二元操作符的二元函数对象类。为二