一、什么是函数对象
在C++中,函数可以被看作是一种对象,这种能够像普通函数一样使用的对象叫做函数对象。函数对象可以携带自己的状态,而且为函数指针提供了更多的灵活性,使得它可以被用于STL等很多其他的应用场景。
在函数对象的实现中,可以使用重载函数调用运算符“()”,这样这个类就可以具有类似函数的功能。在STL中,很多算法接受函数对象作为参数,程序员可以通过实现自己的函数对象来定制一些特定功能。
二、排序算法与函数对象
C++ STL提供了非常丰富的排序算法,比如std::sort()、std::partial_sort()、std::merge()等,这些算法都需要传入一个比较函数作为参数,比较函数的作用是决定元素的排序方式。
比较函数接收两个参数,通常是一个类型为T的指针,如果第一个参数要排在第二个参数之前,需要返回一个小于零的数,如果第一个参数要排在第二个参数之后,需要返回一个大于零的数。如果两个参数相等,需要返回0。
对于基本类型来说,比较函数是非常简单的,但是对于复杂类型来说,比较函数就不是那么好实现了。为了解决这个问题,我们可以使用函数对象来替代函数指针,从而更好地控制排序方式。
三、使用函数对象排序
下面给出一个使用函数对象排序的示例,假设我们有一个结构体表示一个人的信息,包括姓名、年龄和性别:
struct Person {
std::string name;
int age;
char gender;
};
现在我们要按照年龄升序排列这些人的信息,并且对于同龄的人,按照姓名的升序排列,那么可以这样使用函数对象:
struct PersonCmp {
bool operator()(const Person& p1, const Person& p2) const {
if(p1.age != p2.age) {
return p1.age < p2.age;
} else {
return p1.name < p2.name;
}
}
};
int main() {
std::vector<Person> people {
{"Tom", 25, 'M'},
{"Lucy", 20, 'F'},
{"Jack", 20, 'M'},
{"Alice", 22, 'F'}
};
std::sort(people.begin(), people.end(), PersonCmp());
for(auto& person : people) {
std::cout << person.name << " " << person.age << " " << person.gender << std::endl;
}
return 0;
}
上述代码中,我们定义了一个名为PersonCmp的函数对象,它重载了“()”运算符,然后在main函数中,将这个函数对象作为第三个参数传递给std::sort()函数,std::sort()函数会按照函数对象定义的排序方式进行排序。
四、小结
函数对象是C++ STL中非常重要的一个概念,它可以让我们以独立于函数指针的方式实现排序算法,从而更好地控制排序的方式。在实际的开发工作中,我们可以灵活运用函数对象,来达到更好的代码设计和使用效果。