C++STL标准库学习笔记(十一)函数对象

目录

前言:

正文:

1. 函数对象

2. STL中的函数对象类模板

3. greater的应用

4. 在STL中使用自定义的“大”“小”关系

5. 例题:写出MyMax模板

后记:


前言:

        在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来。

        在这一篇文章中,我们主要对STL中的函数对象进行简单的介绍。

正文:

1. 函数对象

        若一个类重载了运算符“()”,则该类的对象就成为函数对象

        例1:

#include<iostream>
using namespace std;

class CMyAverage
{//函数对象类
    public:
    double operator()(int a1,int a2,int a3)
    {
        return (double)(a1+a2+a3)/3;
    }
};

int main(int argc, char const *argv[])
{
    CMyAverage average;//函数对象
    cout<<average(3,2,3);//等价于average.operator()(3,2,3)
    //输出:2.66667
    return 0;
}

        例2:

#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;

int sumSquares(int total, int value)
{
    return total + value*value;
}

template<class T>
void PrintInterval(T first, T last)
{//输出区间[first, last)中的元素
    for (; first != last; ++first)
    {
        cout<<*first<<" ";
    }
    cout<<endl;
}

template<class T>
class SumPowers
{
    private:
    int power;
    public:
    SumPowers(int p):power(p){}
    const T operator()(const T & total, const T & value)
    {//计算value的power次方,加到total上
        T v = value;
        for (int i = 0; i < power-1; i++)
        {
            v = v * value;
        }
        return total + v;
    }
};

int main(int argc, char const *argv[])
{
    const int SIZE = 10;
    int a1[] = {1,2,3,4,5,6,7,8,9,10};
    vector<int> v(a1,a1+SIZE);
    cout<<"1)";
    PrintInterval(v.begin(),v.end());
    int result = accumulate(v.begin(),v.end(),0,sumSquares);
    //求出v上面所有元素的平方和
    cout<<"2)平方和"<<result<<endl;
    result = accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
    //SumPowers<int>(3)中,这是一个对象,其中power = 3
    //求出v上面所有元素的立方和
    cout<<"3)立方和"<<result<<endl;
    result = accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
    cout<<"4)4次方和"<<result<<endl;
    return 0;
}
/*
输出:
1)1 2 3 4 5 6 7 8 9 10 
2)平方和385
3)立方和3025
4)4次方和25333
*/

        其中:

        在int result = accumulate(v.begin(),v.end(),0,SumSquares)

        这段代码中,实例化出:

int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, int(*op)(int,int))
{
    for (; first != last; ++first)
    {
        init = op(init,*first);
    }
    return init;
}

        而在accumulate(v.begin(),v.end(),0,SumPowers<int>(3));

        实例化出:

int accumlate(vector<int>::iterator first, vector<int>::iterator last, int init, SumPowers<int>op)
{
    for (; first != last; ++first)
    {
        init = op(init,*first);
    }
    return init;
}

        函数对象的价值:

        在刚刚的例子中,假使我们要求一个数组的1,2,3,4,5,6,7,8,9....次方和,如果不使用函数对象的话,就要可能要写n多个函数(虽然老师是这样说的,但是我传进去一个参数来知道做几次方不好吗,不过从这个例子中看,accumulate支持的函数似乎只支持两个参数传入,一个init,一个value,这种情况看来还是得用函数对象)

2. STL中的函数对象类模板

        以下模板可以用来生成函数对象。

        equal_to

        greater

        less

        ......

        它们都是模板而且也实现了“()”这个成员函数

        都在头文件:<functional>里定义了

        如:

template<class T>
struct greater:public binary function<T,T,bool>
{
    bool operator()(const T&x,const T&y)const
    {
        return x > y;
    }
};

3. greater的应用

        list有两个sort成员函数

        void sort();

                将list中的元素按“<”规定的比较方法升序排列。

        template<class Compare>

        void sort(Compare op)

        将list中的元素按op规定的比较方法升序排序。即要比较x,y大小时,看op(x,y)的返回值,为true则认为x小于y

        样例:

#include<list>
#include<iostream>
using namespace std;

class myless
{

public:
    bool operator()(const int & c1, const int & c2)
    {
        return (c1 % 10)<(c2 % 10);//比较个位数大小
    }
};
template<class T>
void Print(T first, T last)
{
    for (; first != last; ++first)
    {
        cout<<*first<<",";
    }
    
}

int main(int argc, char const *argv[])
{
    const int SIZE = 5;
    int a[SIZE] = {5,21,14,2,3};
    list<int> lst(a,a+SIZE);
    lst.sort(myless());
    Print(lst.begin(),lst.end());
    cout<<endl;//输出:21,2,3,14,5,
    lst.sort(greater<int>());//greater<int>()是个对象
    Print(lst.begin(),lst.end());
    cout<<endl;//输出:21,14,5,3,2,
    return 0;
}

        这个没有什么特别需要强调的。

4. 在STL中使用自定义的“大”“小”关系

        关联容器和STL中许多算法,都是可以用函数或函数对象自定义比较器的。在自定义了比较器op的情况下,以下三种说法是等价的:

        1)x小于y

        2)op(x,y)返回值为true

        3)y大于x

5. 例题:写出MyMax模板

#include<iostream>
#include<iterator>
using namespace std;

class MyLess
{
public:
    bool operator()(int a1, int a2)
    {
        if((a1%10)<(a2%10))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

bool Mycompare(int a1, int a2)
{
    if((a1%10)<(a2%10))
    {
        return false;
    }
    else
    {
        return true;
    }
    
}

template<class T, class Pred>
T MyMax(T first, T last, Pred myless)
{
    T tmpMax = first;
    for (; first != last; ++first)
    {
        if (myless(*tmpMax, *first))
        {
            tmpMax = first;
        }
        
    }
    return tmpMax;
}

int main(int argc, char const *argv[])
{
    int a[] = {35,7,13,19,12};
    cout<<*MyMax(a,a+5,MyLess())<<endl;//输出:19
    cout<<*MyMax(a,a+5,Mycompare)<<endl;//输出:12
    return 0;
}

后记:

        到了这一节就感觉内容抽象了许多,但是c++对这些东西(指函数里面套函数)的支持还是让人感觉很惊喜的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值