c++ STL函数对象

1. 函数对象

1.1 函数对象概念

概念:

重载函数调用符号()的类,其对象常被称为函数对象
函数对象使用重载的()时,行为类似函数调用,也叫仿函数

本质:

函数对象(防函数)是一个类,不是一个函数

1.2 函数对象使用:

特点:

函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
函数对象可以有自己的状态,可以做一些状态记录工作
函数对象可以做为参数传递
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//函数对象 防函数

class MyAdd {
public:
    int operator()(int v1, int v2) {
        return v1 + v2;
    }
};




// 1. 函数对象在使用时,可以像普通函数一样,可以有参数传递,可以有返回值
void test01() {
    MyAdd myAdd;
    cout << myAdd(10, 20) << endl;
}

// 2. 函数对象可以有自己的状态,可以做简单的缓存

class MyPrint {
public:
    void operator()(string text) {
        cout << text << endl;
        count++;
    }
    int count = 0;

    void add() {
        cout << "add" << endl;
    }
};

void test02() {
    MyPrint myPrint;
    myPrint("hello world");
    myPrint("西施很漂亮");
    myPrint("西施很漂亮");
    myPrint("西施很漂亮");
    myPrint("西施很漂亮");
    myPrint.add(); // 成员函数
    cout << myPrint.count << endl;
}

// 3. 函数对象可以作为参数传递
void doPrint(MyPrint &myPrint, string text) {
    myPrint(text);
}

void test03() {
    MyPrint myPrint;
    doPrint(myPrint, "西施很漂亮");
}

int main(int argc, char const *argv[]) {
    test03();
    return 0;
}


2 谓词

2.1. 谓词的概念

概念:

返回bool类型的防函数称为谓词
如果operator()接受一个参数,么叫一元谓词
如果operator()接受两个参数,么叫二元谓词

2.2. 一元谓词

#include 
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

// 一元谓词

class GreateFive {
public:
    bool operator()(int val) {  
        return val > 5;
    }
};

void test01() {
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    // 查找容器中有没有大于5的元素
    vector<int>::iterator it = find_if(v.begin(), v.end(), GreateFive());
    if (it == v.end()) {
        cout << "没有找到" << endl;
    }
    else {
        cout << "找到大于5的数字为:" << *it << endl;
    }
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}


2.3 二元谓词

#include 
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//  二元谓词

class myCompare {
public:
    bool operator()(int val, int val2) {  
        return val > val2;
    }
};

void test01() {
    vector<int> v;
    v.push_back(10);
    v.push_back(30);
    v.push_back(50);
    v.push_back(40);
    v.push_back(20);

    sort(v.begin(), v.end());
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
        cout << *it << " ";
    }
    cout << endl;
    
    // 使用函数对象,排序规则为从大到小
    sort(v.begin(), v.end(), myCompare());
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
        cout << *it << " ";
    }
    cout << endl;
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}


sort 源码

template<typename _RandomAccessIterator, typename _Compare>
    _GLIBCXX20_CONSTEXPR
    inline void
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
	 _Compare __comp)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
	    _RandomAccessIterator>)
      __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
	    typename iterator_traits<_RandomAccessIterator>::value_type,
	    typename iterator_traits<_RandomAccessIterator>::value_type>)
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_irreflexive_pred(__first, __last, __comp);

      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
    }

	template <typename _Compare>
    struct _Iter_comp_iter
    {
      _Compare _M_comp;

      explicit _GLIBCXX14_CONSTEXPR
      _Iter_comp_iter(_Compare __comp)
          : _M_comp(_GLIBCXX_MOVE(__comp))
      {
      }

      template <typename _Iterator1, typename _Iterator2>
      _GLIBCXX14_CONSTEXPR bool
      operator()(_Iterator1 __it1, _Iterator2 __it2)
      {
        return bool(_M_comp(*__it1, *__it2));
      }
    };

    template <typename _Compare>
    _GLIBCXX14_CONSTEXPR inline _Iter_comp_iter<_Compare>
    __iter_comp_iter(_Compare __comp)
    {
      return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp));
    }

可以看到sort 中需要的是_Iter_comp_iter,bool(_M_comp(*__it1, *__it2)) 需要的就是二元谓词

3 内建函数对象

3.1 内建函数对象意义

概念:

stl内建了一些函数对象

分类:

算术防函数
关系防函数
逻辑防函数

用法:

这些防函数所产生的对象,用法和一般函数完全相同
使用内建函数对象,需要引入头文件 #include

3.2 算术防函数

功能描述:

实现四则运算
其中negate是一元元算,其他都是二元元算

防函数原型:

template  T plus(T a, T b)  // 加法
template  T minus(T a, T b)  // 减法
template  T multiply(T a, T b)  // 乘法
template  T divide(T a, T b)  // 除法
template  T mod(T a, T b)  // 取模
template  T negate(T a)  // 取反
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//  算术防函数
void test01() {
    // negate 一元防函数 取反
    negate<int> n;
    cout << n(50) << endl;

    // 二元防函数 加法
    plus<int> p;
    cout << p(10, 20) << endl;

    plus<string> p2;
    cout << p2("hello", "world") << endl;

    // 减法
    minus<int> m;
    cout << m(10, 20) << endl;
}

int main(int argc, char const *argv[]) {
    test01();
    return 0;
}


3.3 关系防函数

防函数原型

template equal_to; // 等于
template not_equal_to; // 不等于
template greater; // 大于
template greater_equal; // 大于等于
template less; // 小于
template less_equal; // 小于等于
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//  关系防函数

class Person
{
public:
    Person(string name, int age) : name(name), age(age) {}
    string name;
    int age;
    // 大于 const 是必要的
    bool operator>(const Person &p) const
    {
        return this->age > p.age;
    }
};


void test01()
{
    vector<int> v;
    v.push_back(80);
    v.push_back(20);
    v.push_back(60);
    v.push_back(40);
    v.push_back(50);

    // 大于
    greater<int> g1;
    // 使用内建函数对象 实现降序
    sort(v.begin(), v.end(), g1);

    for (auto it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    // 实现自定义数据类型 降序
    vector<Person> vp;
    vp.push_back(Person("西施", 20));
    vp.push_back(Person("王昭君", 18));
    vp.push_back(Person("杨玉环", 16));
    vp.push_back(Person("貂蝉", 19));
    vp.push_back(Person("小乔", 17));

    sort(vp.begin(), vp.end(), greater<Person>());

    for (auto it = vp.begin(); it != vp.end(); it++)
    {
        cout << "name: " << it->name << "\t age: " << it->age << endl;
    }
}

int main(int argc, char const *argv[])
{
    test01();
    return 0;
}

3.4 逻辑防函数

函数原型:

template  bool logical_and::operator()(const T& x, const T& y) const; // 逻辑与
template  bool logical_or::operator()(const T& x, const T& y) const; // 逻辑或
template  bool logical_not::operator()(const T& x) const; // 逻辑非
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//  逻辑防函数


void test01()
{
    // 逻辑非
    vector<bool> vb;
    vb.push_back(true);
    vb.push_back(false);
    vb.push_back(true);
    vb.push_back(false);

    for(vector<bool>::iterator it = vb.begin(); it != vb.end(); it++){
        cout << *it << " ";
    }
    cout << endl;
    
    cout << "逻辑非" << endl;
    vector<bool> vb2;
    vb2.resize(vb.size());

    transform(vb.begin(), vb.end(), vb2.begin(), logical_not<bool>());
    for(vector<bool>::iterator it = vb2.begin(); it != vb2.end(); it++){
        cout << *it << " ";
    }
    cout << endl;
}

int main(int argc, char const *argv[])
{
    test01();
    return 0;
}

你可能感兴趣的:(c++学习笔记,c++,算法,开发语言)