C++ STL 之 函數對象適配器

謂詞是指普通函數或重載的 operator()返回值是 bool 類型的函數對象(仿函數)。若是operator 接受一個參數,那麼叫作一元謂詞,若是接受兩個參數,那麼叫作二元謂詞,謂詞可做爲一個判斷式。
例如:ios

struct myfuncobj01
{
  bool operator(int v){} // 接受一個參數,而且返回值爲 Bool 即一元謂詞
}
bool compare01(int v); // 一樣是叫作一元謂詞
struct myfuncobj02
{
  bool operator(int v1,int v2){} // 接受兩個參數,返回值爲 Bool 即二元謂詞
}
bool compare02(int v1,int v2); // 一樣是叫作二元謂詞

函數對象適配器是完成一些配接工做,這些配接包括綁定(bind),否認(negate),以及對通常函數或成員函數的修飾,使其成爲函數對象。
若是但願函數對象適配器能對咱們本身編寫的函數對象有效,咱們須要根據咱們的函數對象類型繼承 STL 的父類對象。
若是你自己是二元函數對象 須要繼承
二元函數繼承:public binary_function<參數類型,參數類型,返回類型>
一元函數繼承:public unary_function<參數類型,返回類型>算法

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

struct MyPrint : public binary_function<int, int, void>
{
    void operator()(int v, int val) const
    {
        cout << "v = " << v << " val = " << val << endl;
        cout << "v + val = " << v + val << endl;
    }
    
};

// 仿函數適配器 bind1st bind2nd 綁定適配器
void test01()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    int addNum = 200;
    for_each(v.begin(), v.end(), bind2nd(MyPrint(), addNum));
    // 綁定適配器  將一個二元函數對象轉變成一元函數對象
    // bind1st bind2nd區別?
    // bind1st,將addNum綁定爲函數對象的第一個參數
    // bind2nd,將addNum綁定爲函數對象的第二個參數
    cout << "----------------------" << endl;
}

struct MyPrint02
{
    void operator()(int v)
    {
        cout << v << " ";
    }
};

struct MyCompare : public binary_function<int, int, bool>
{
    bool operator()(int v1, int v2) const
    {
        return v1 > v2;
    }
};

struct MyGreater5 : public binary_function<int, int, bool>
{
    bool operator()(int v, int val) const
    {
        cout << "v = " << v << " val = " << val << endl;
        return v > val;
    }
};

// 仿函數適配器 not1 not2 取反適配器
void test02()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    for_each(v.begin(), v.end(), MyPrint02());
    cout << endl;
    // 正常排序 從大到小
    sort(v.begin(), v.end(), MyCompare());
    for_each(v.begin(), v.end(), MyPrint02());
    cout << endl;
    // 取反以後從小到大
    sort(v.begin(), v.end(), not2(MyCompare()));
    for_each(v.begin(), v.end(), MyPrint02());
    cout << endl;
    // not1 not2 
    // 若是對二元謂詞取反,用not2
    // 若是對一元謂詞取反,用not1
    vector<int>::iterator it = find_if(v.begin(), v.end(), not1(bind2nd(MyGreater5(), 11)));
    if (it == v.end())
    {
        cout << "沒有找到!" << endl;
    }
    else
    {
        cout << *it << endl;
    }
    cout << "----------------------" << endl;
}

// 仿函數適配器 ptr_fun
void MyPrint03(int val, int val2)
{
    cout << "val = " << val << " val2 = " << val2 << endl;
    cout << "val + val2 = " << val + val2 << endl;
}

void test03()
{
    vector<int> v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }
    // ptr_func把普通函數轉成函數對象
    for_each(v.begin(), v.end(), bind2nd(ptr_fun(MyPrint03), 10));
    cout << "--------------" << endl;
}

// 成員函數適配器 mem_fun mem_fun_ref
class Person
{
public:
    Person(int age, int id) : age(age), id(id){}
    void show()
    {
        cout << "age = " << age << " id = " << id << endl;
    }
public:
    int age;
    int id;
};

void test04()
{
    // 若是容器中存放的對象或者對象指針,咱們for_each算法打印的時候,調用類本身提供的打印函數
    vector<Person> v;
    Person p1(10, 20), p2(30, 40), p3(50, 60);
    v.push_back(p1);
    v.push_back(p2);
    v.push_back(p3);
    for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));
    cout << "--------------" << endl;
    vector<Person*> v1;
    v1.push_back(&p1);
    v1.push_back(&p2);
    v1.push_back(&p3);
    for_each(v1.begin(), v1.end(), mem_fun(&Person::show));
    // mem_fun_ref mem_fun區別?
    // 若是存放的是對象指針 使用mem_fun
    // 若是使用的是對象 使用mem_fun_ref
}

int main()
{
    test01();
    test02();
    test03();
    test04();
    getchar();
    return 0;
}
相關文章
相關標籤/搜索