C++ 函数对象

C++ 函数对象(也称为函数式对象)是一个可以像函数一样被调用的类或结构体对象。

它重载了 **函数调用运算符** (),允许我们将对象用作函数。


在C++中创建函数对象

我们可以在C++中这样创建函数对象:

class Greet {
  public:
    void operator()() {
      // function body
    }
};

在这里,我们重载了函数调用运算符 ()。这允许我们像调用函数一样调用类对象,如下所示:

// create an instance of Greet
Greet greet;

// call the object as a function
greet(); 

注意:在重载类的 () 运算符时,请记住设置 public 访问修饰符,因为默认情况下类的成员是 private 的。


示例 1:C++ 函数对象

#include <iostream>
using namespace std;

class Greet { public: // overload function call/parentheses operator void operator()() { cout << "Hello World!"; } };
int main() { // create an object of Greet class Greet greet;
// call the object as a function greet();
return 0; }

输出

Hello World!

在上面的示例中,我们创建了一个简单的程序,使用C++函数对象打印 Hello World!

为了创建函数对象,我们首先需要创建一个类,该类的对象可以像函数一样调用。因此,我们创建了一个名为 Greet 的类。

在 Greet 类内部

这里,我们使用了以下方式重载了函数调用运算符 ()

class Greet {

public:
  // overload function call operator
  void operator()() {
    cout << "Hello World!";
  }
};

在这里,我们重载的函数只是打印 Hello World!

在 main() 函数内部

这里,我们从 Greet 类创建了一个名为 greet 的对象。

Greet greet;

现在,我们使用 () 运算符调用 greet 对象

// displays "Hello World!"
greet() 

或者,我们可以使用以下代码调用 greet

// displays "Hello World!"
greet.operator()();

带返回类型和参数的C++函数对象

我们还可以定义一个接受参数并返回值 的函数对象。例如:

#include <iostream>
using namespace std;

class Add {

  public:
// overload function call operator // accept two integer arguments // return their sum int operator() (int a, int b) { return a + b; }
}; int main() { // create an object of Add class Add add;
// call the add object int sum = add(100, 78);
cout << "100 + 78 = " << sum; return 0; }

输出

100 + 78 = 178

在上面的示例中,我们使用了一个具有整数返回类型和两个整数参数的函数对象来计算它们的和。

class Add {
  public:
    int operator()(int a, int b) {
      return a + b;
    }
};

main() 中,我们从 Add 类创建了 add 对象。

然后,我们使用参数 **100** 和 **78** 调用 add 对象。函数对象的返回值被赋给 sum 变量。

// returns 178
int sum = add(100, 78);

示例 2:带成员变量的C++函数对象

#include<iostream>
using namespace std;

class Add_To_Sum {

  private:
int initial_sum;
public: // constructor to initialize member variable Add_To_Sum(int sum) { initial_sum = sum; }
// overload function call operator int operator()(int num) { return initial_sum + num; }
}; int main() { // create object of Add_To_Sum class // initialize member variable of object with value 100 Add_To_Sum add = Add_To_Sum(100);
// call the add object with 78 as argument int final_sum = add(78);
cout << "100 + 78 = " << final_sum; return 0; }

输出

100 + 78 = 178

在上面的示例中,Add_To_Sum 类有一个成员变量 initial_sum。我们使用构造函数初始化了这个变量

// constructor to initialize member variable
Add_To_Sum(int sum) {
  initial_sum = sum;
}

然后,我们重载了函数调用运算符,该运算符:

  • 将参数 num 添加到 initial_sum 变量中
  • 然后返回 result
int operator()(int num) {
  return initial_sum + num;
}

main() 中,我们使用带参数的构造函数将 add 对象的 initial_sum 变量初始化为 **100**。

// initialize initial_sum variable to 100
Add_To_Sum add = Add_To_Sum(100);

最后,我们调用函数对象并将 **78** 作为参数传递。

// returns sum of 100 and 78 i.e 178
int final_sum = add_to_100(78); 

C++ 预定义函数对象

通过包含 functional 头文件,我们可以使用标准库提供的预定义函数对象。

#include <functional>

C++ 为算术、关系和逻辑运算提供了以下库函数对象。

1. 算术函数对象

函数对象 描述
plus 返回两个参数的和
minus 返回两个参数的差
multiplies 返回两个参数的积
divides 返回两个参数相除后的结果
modulus 返回两个参数相除后的余数
negate 返回参数的负值

2. 关系函数对象

函数对象 描述
equal_to 如果两个参数相等,则返回 true
not_equal_to 如果两个参数不相等,则返回 true
greater 如果第一个参数大于第二个参数,则返回 true
greater_equal 如果第一个参数大于或等于第二个参数,则返回 true
less 如果第一个参数小于第二个参数,则返回 true
less_equal 如果第一个参数小于或等于第二个参数,则返回 true

3. 逻辑函数对象

函数对象 描述
logical_and 返回两个布尔值的 **逻辑与** 操作结果
logical_or 返回两个布尔值的 **逻辑或** 操作结果
logical_not 返回布尔值的 **逻辑非** 操作结果

4. 位运算函数对象

函数对象 描述
bit_and 返回两个参数的 **按位与** 操作结果
bit_or 返回两个参数的 **按位或** 操作结果
bit_xor 返回两个参数的 **按位异或** 操作结果

示例 3:使用 STL 的C++预定义函数对象

通常,函数对象与C++ STL一起使用,作为STL算法(如 sortcount_ifall_of 等)的参数。

在此示例中,我们将使用预定义的C++函数对象 greater<T>(),其中 T 是函数对象参数的类型,并结合STL算法 sort

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std; int main() { // initialize vector of int vector<int> nums = {1, 20, 3, 89, 2};
// sort the vector in descending order sort(nums.begin(), nums.end(), greater<int>());
for(auto num: nums) { cout << num << ", "; } return 0; }

输出

89, 20, 3, 2, 1

在上面的示例中,我们使用了一个预定义的函数对象来以降序对整数向量(名为 nums)进行排序。

默认情况下,sort() 函数按升序对元素进行排序。

为了使其按降序排序,我们使用了预定义的函数对象 greater<T>

sort(nums.begin(), nums.end(), greater<int>());

请注意,我们使用了代码 greater<int>()。这是因为 nums 是一个整数向量,因此我们在 T 的位置使用了 int

最后,我们使用范围for循环打印排序后的向量。


常见问题

如何使用C++结构体创建函数对象?
#include <iostream>
using namespace std;

struct Greet { // overload function call/parentheses operator void operator()() { cout << "Hello World!"; } };
int main() { // create a variable of Greet struct Greet greet; // call the struct variable as a function greet(); return 0; }

输出

Hello World!

在上面的示例中,我们创建了一个名为 Greetstruct 并重载了 () 运算符来打印 Hello World!

main() 中,我们创建了 Greet 的一个变量,并通过 () 运算符调用了函数对象:

Greet greet;

// Output: Hello World!
greet();
如何将自定义函数对象与STL算法一起使用?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Even_Counter {

  public:
// overload function call operator // returns true if the n is even bool operator()(int n) { return n % 2 == 0; }
}; int main() { // initialize vector of integers vector<int> nums = {1, 2, 3, 4, 5, 8, 10, 12};
// create an object of Even_Counter Even_Counter even_counter; // count the number of even numbers in the vector int even_count = count_if(nums.begin(), nums.end(), even_counter);
cout << "There are " << even_count << " even numbers."; return 0; }

输出

There are 5 even numbers.

在上面的示例中,我们使用了 **自定义函数对象** 和STL算法 count_if 来计算 vector nums 中偶数的总数。

我们创建了一个名为 Even_Counter 的类,并重载了函数调用运算符,使其在数字是偶数时返回 true

bool operator()(int n) {
  return n % 2 == 0;
}

main() 中,我们创建了一个名为 nums 的整数 vector 和一个名为 even_counterEven_Counter 对象。

然后,我们使用 count_if 算法来计算 nums 中偶数的数量。

int even_count = count_if(nums.begin(), nums.end(), even_counter);

请注意,我们将 even_counter 函数对象作为第三个参数传递给了 count_if

even_counter 函数对象以当前向量元素 n 作为其参数,并在 n 是偶数时返回 true

我们如何创建泛型函数对象?

我们可以通过重载带有类型参数的函数调用运算符来创建泛型函数对象。为此,我们需要使用 类模板

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

template<typename T> class Greater_Than { public: // returns true if left is greater than right bool operator()(const T &left, const T &right) { return left > right; } };
int main() { // initialize vector of int vector<int> int_nums = {1, 20, 3, 89, 2}; // sort the vector in descending order
sort(int_nums.begin(), int_nums.end(), Greater_Than<int>());
for(auto num: int_nums) { cout << num << ", "; } return 0; }

输出

89, 20, 3, 2, 1

在上面的示例中,我们实现了一个 Greater_Than<T> 函数对象,其功能类似于C++预定义函数 greater<int>

默认情况下,STL sort() 函数按升序对元素进行排序。

在 Greater_Than 类内部

template<typename T>
class Greater_Than {
  public:
    bool operator()(const T &left,const T &right) {
      return left > right;
    }
};

在 main() 函数内部

我们初始化了一个整数向量 int_nums。然后,我们使用STL sort() 函数对向量进行排序。

// sort the vector in descending order
sort(int_nums.begin(), int_nums.end(), Greater_Than<int>());

请注意,我们没有创建 Greater_Than 类的对象,而是将 Greater_Than<int>() 作为第三个参数传递,这会创建一个函数对象。

这相当于

Greater_Than<int> greater_than;

// sort the vector in descending order
sort(int_nums.begin(), int_nums.end(), greater_than);
你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战