24、函数对象与谓词

厨子大约 3 分钟C++C++基础编程程序厨

函数对象(Function Object)在C++中比较常用,它允许将函数作为对象来处理,提高代码的灵活性和可复用性。

谓词(Predicate)是一种特殊的函数对象,用于返回布尔值。

本文会介绍相关概念。

函数对象

函数对象是一个类对象,它重载了函数调用运算符operator(),使得对象可以像函数一样被调用。函数对象可以存储状态,并且可以作为参数传递给算法。它通常通过定义一个类并重载operator()来实现。

代码示例:

#include <iostream>

// 定义一个函数对象类
class Add {
public:
    int operator()(int a, int b) const {
        return a + b;
    }
};

int main() {
    Add add; // 创建函数对象
    int result = add(3, 4); // 调用函数对象
    std::cout << "Result: " << result << std::endl; // 输出:7
    return 0;
}

谓词

谓词是一种返回布尔值的函数或函数对象,它通常用于条件判断。谓词可以分为一元谓词(接受一个参数)和二元谓词(接受两个参数)。

谓词常用于STL算法中,比如std::find_ifstd::remove_if等。

一元谓词:

#include <iostream>
#include <vector>
#include <algorithm>

// 定义一元谓词
class IsEven {
public:
    bool operator()(int num) const {
        return num % 2 == 0;
    }
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用std::find_if查找第一个偶数
    std::vector<int>::iterator it = std::find_if(vec.begin(), vec.end(), IsEven());
    if (it != vec.end()) {
        std::cout << "First even number: " << *it << std::endl; // 输出:2
    } else {
        std::cout << "No even number found." << std::endl;
    }

    return 0;
}

二元谓词:

#include <iostream>
#include <vector>
#include <algorithm>

// 定义二元谓词
class Compare {
public:
    bool operator()(int a, int b) const {
        return a > b; // 降序排序
    }
};

int main() {
    std::vector<int> vec = {5, 3, 1, 4, 2};

    // 使用std::sort和二元谓词进行降序排序
    std::sort(vec.begin(), vec.end(), Compare());

    // 输出排序后的vector
    for (int num : vec) {
        std::cout << num << " "; // 输出:5 4 3 2 1
    }
    std::cout << std::endl;

    return 0;
}

内置函数对象与适配器

标准库中的函数对象

STL提供了许多内置的函数对象,定义在<functional>头文件中。常见的函数对象有:

  • 算术运算std::plusstd::minusstd::multipliesstd::dividesstd::modulusstd::negate
  • 关系运算std::equal_tostd::not_equal_tostd::greaterstd::lessstd::greater_equalstd::less_equal
  • 逻辑运算std::logical_andstd::logical_orstd::logical_not

示例代码,greater

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
    std::vector<int> vec = {5, 3, 1, 4, 2};

    // 使用std::sort和std::greater进行降序排序
    std::sort(vec.begin(), vec.end(), std::greater<int>());

    // 输出排序后的vector
    for (int num : vec) {
        std::cout << num << " "; // 输出:5 4 3 2 1
    }
    std::cout << std::endl;

    return 0;
}

函数对象适配器

函数对象适配器用于修改或组合现有的函数对象,常见的适配器有std::bindstd::bind1st(C++17已移除)、std::bind2nd(C++17已移除)

std::bind示例代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用std::bind绑定std::greater的第二个参数为3
    auto greaterThan3 = std::bind(std::greater<int>(), std::placeholders::_1, 3);

    // 使用std::find_if查找第一个大于3的元素
    std::vector<int>::iterator it = std::find_if(vec.begin(), vec.end(), greaterThan3);
    if (it != vec.end()) {
        std::cout << "First number greater than 3: " << *it << std::endl; // 输出:4
    } else {
        std::cout << "No number greater than 3 found." << std::endl;
    }

    return 0;
}

练习

  1. 定义一个函数对象类Multiply,用于计算两个数的乘积,并使用std::transform将其应用于一个std::vector
  2. 使用std::bindstd::less实现一个函数对象,用于判断一个数是否小于10,并使用std::count_if统计std::vector中小于10的元素个数。