赞
踩
函数对象是“重载函数调用操作符”的类,由于其使用时类似于调用一个函数,所以也称作“仿函数”。
通俗来讲,就是我们构建一个类,在类的内部重载了“()”操作符,然后在使用的时候我们可以像调用函数一样来调用类的对象。
不同于普通的函数,函数对象可以拥有自己的状态。
典型的,我们调用std::sort进行排序的时候,如果我们使用的是int、float等普通的数据类型,那么我们可以使用默认的排序方法。但是对于一些自定义结构化数据,我们就需要自行创建一个排序的方法。
- #include <algorithm>
-
- #include <vector>
-
- #include <string>
-
- #include <iostream>
-
-
- /** 自定义结构体. */
-
- struct Person {
-
- std::string name;
-
- int age;
-
- Person(std::string n, int a) : name(std::move(n)), age(a) {}
-
- };
-
-
-
- /** 函数对象(仿函数) */
-
- struct AgeComparator {
-
- bool operator()(const Person& a, const Person& b) const {
-
- return a.age < b.age;
-
- }
-
- };
-
-
-
- int main(int argc, char* argv[])
-
- {
-
- std::vector<Person> people = {
-
- Person("Alice", 30),
-
- Person("Bob", 20),
-
- Person("Charlie", 25)
-
- };
-
-
-
- /** 使用AgeComparator函数对象进行排序. */
-
- std::sort(people.begin(), people.end(), AgeComparator());
-
-
-
- for (const auto& person : people) {
-
- std::cout << person.name << ": " << person.age << std::endl;
-
- }
-
-
-
- return 0;
-
- }
除了上述使用方式以外,还可以在查找函数std::find_if,std::count_if
等函数中作为功能块进行使用。
要创建一个函数对象,我们首先需要定义一个类,并重载它的operator()。这个操作符可以重载为接受不同数量的参数,从而实现不同的行为。下面是一个简单的函数对象示例:
- class Adder {
-
- public:
-
- int operator()(int a, int b)
-
- {
-
- return a + b;
-
- }
-
- };
在这个例子中,Adder类定义了一个接受两个整数参数并返回它们的和的函数对象。我们可以通过创建Adder类的实例并调用它,就像调用一个普通函数一样:
Adder adder;
int result = adder(3, 4); ///< result 等于 7
前面讲到,函数对象可以拥有自己的状态信息。
通俗讲,函数对象本身是一个类,所有自然是可以拥有一些数据成员。这些数据成员就可以作为状态载体来使用。话不多说,直接上例程。
- class Counter {
-
- public:
-
- int count() { return ++total; }
-
- private:
-
- static int total;
-
- };
-
-
- int Counter::total = 0;
-
- /** 使用函数对象. */
-
- Counter counter;
-
- for (int i = 0; i < 5; ++i) {
-
- std::cout << counter() << std::endl; ///< 输出 1, 2, 3, 4, 5
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。