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算法(如 sort
、count_if
、all_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循环打印排序后的向量。
常见问题
#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!
在上面的示例中,我们创建了一个名为 Greet
的 struct
并重载了 ()
运算符来打印 Hello World!
。
在 main()
中,我们创建了 Greet
的一个变量,并通过 ()
运算符调用了函数对象:
Greet greet;
// Output: Hello World!
greet();
#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_counter 的 Even_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);