函数对象 仿函数

最后更新于 2022-12-06 5784 次阅读


概念

  • 重载函数调用操作符的类,其对象称为函数对象
  • 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
  • 本质是一个类

1.可以像普通函数一样调用 有返回值 有参数列表

class AddClass
{
public:
    int operator()(int v1, int v2) //()重载
    {
        return v1 + v2;
    }
};

void test()
{
    AddClass MyAdd;
    cout << MyAdd(10, 10);
}
main()
{
    test();
    return 0;
}

//20

函数对象超出普通函数的概念 可以拥有自己的状态 比如计数器

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

void test()
{
    PrintClass MyPrint;
    MyPrint("ahhhhh");
    MyPrint("ahhhhh");
    MyPrint("ahhhhh");
    MyPrint("ahhhhh");

    cout << MyPrint.count << endl;
}

main()
{
    test();
    return 0;
}

//4

普通函数无法做到 因为这是一个类

函数对象可以作为参数传递

class PrintClass
{
public:
    void operator()(string test)
    {
        cout << test << endl;
    }
};

void doPrint(PrintClass &mp, string test)
{
    mp(test);
}

void test02()
{
    PrintClass MyPrint2;
    doPrint(MyPrint2, "Hello CPP");
}
main()
{
    test02();
    return 0;
}

因为重载了(),所以可以在正常函数上使用她做参数,再在这个函数函数体里用类对象本身()的重载放入参数实现。

就是感觉这样做挺复杂的…不知道效率有多高

谓词

  • 返回bool类型的仿函数成为谓词
  • 如果operator()里接收一个参数 叫做一元谓词
  • 接收两个叫二元谓词

一元谓词

概念:携带一个参数的仿函数且返回类型为bool的仿函数

实现:在operator()重载时只有一个参数

class GreaterFive
{
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(), GreaterFive());
    if (it == v.end())
    {
        cout << "not found" << endl;
    }
    else
    {
        cout << "found" << *it << endl;
    }
}

int main()
{
    test01();

    return 0;
}

//found6

二元谓词

就是两个参数 没什么好说的..

class GreaterFive
{
public:
    bool operator()(int val1, int val2)
    {
        return val2 > val1;
    }
};

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(), GreaterFive());
    sort(v.begin(), v.end());

    sort(v.begin(), v.end(), GreaterFive());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
}

int main()
{
    test01();

    return 0;
}

//0 1 2 3 4 5 6 7 8 9 

STL内建函数对象

使用内建函数对象应使用 头文件

之前的谓词是自定义函数 STL更专业全面一点 他为你提供了模板

算数仿函数

实现四则运算

negate是一元 其他都是二元

  • template T plus 加法
  • minus 减法
  • multiplies 乘法
  • divides 除法
  • modulus 取模
  • negate 取反
void test()
{
    negate<int> p;
    cout << p(50) << endl;

    minus<int> m;
    cout << m(2, 3) << endl;

    plus<int> plus;
    cout << plus(2, 3) << endl;

    multiplies<int> mu;
    cout << mu(2, 3) << endl;

    divides<int> d;
    cout << d(4, 2) << endl;

    modulus<int> s;
    cout << s(4, 3) << endl;
} 

关系仿函数

实现关系对比

  • template bool equal_to //等于
  • template bool not_equal_to //不等于
  • template bool greater //大于
  • template bool greater_equal //大于等于
  • template bool less //小于
  • template bool less_equal //小于等于
void test02()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(50);
    v.push_back(30);
    v.push_back(10);
    v.push_back(20);

    //降序
    sort(v.begin(), v.end(), greater<int>());

    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

### 逻辑仿函数

实现逻辑运算

  • template bool logical_and //逻辑与
  • template bool logical_or //逻辑或
  • template bool logical_not //逻辑非

常用遍历算法

for_each

class Print
{
public:
    void operator()(int v)
    {
        cout << v << " ";
    }
};

void print(int v)
{
    cout << v << " ";
}

void test()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }

    for_each(v.begin(), v.end(), Print());
}

int main()
{
    test();
    return 0;
}