C++:函数对象、STL 提供的函数对象、函数适配器详解
函数对象是一种封装了函数行为的对象,它可以像函数一样执行。在 C++ 中,任何符合特定原型的类实例都可以被当做函数对象使用。
STL 中提供了一些函数对象(如算术、逻辑、关系型操作符等),可以方便地进行一些常见操作。
函数适配器是一种用来修改已有函数对象行为的对象。它可以帮助将一个函数对象从一种类型适配到另一种类型,以便于执行某些操作。
函数对象
函数对象是 C++ 中的一个重要概念。它代表了一个类实例,封装了某种函数行为。按照语法和语义,函数对象更像一个“可调用对象”,可以使用调用运算符“()”进行调用。
函数对象的用途非常广泛,有时可以看作是函数指针的升级,但更加灵活和强大。它允许我们使用类的成员变量和成员函数来支持状态,因此可以应用于许多高级算法和模板实现中。
以下是一个简单的函数对象示例:
#include <iostream>
class MyFunctor {
public:
void operator() (const std::string &s) {
std::cout << "Hello, " << s << std::endl;
}
};
int main() {
MyFunctor func;
func("world");
return 0;
}
在上面的示例中,MyFunctor
类实现了调用运算符,使其可以像函数一样调用。在 main
函数中,将一个 MyFunctor
实例作为函数对象,传入一个字符串进行调用。
STL 提供的函数对象
STL 提供了一些函数对象来完成常见的操作。以下是几个常见的示例:
1. 算术操作符
STL 提供了多个算术操作符函数对象,如 plus
、minus
、multiplies
、divides
等。这些函数对象可以通过头文件 <functional>
导入。
#include <functional>
#include <iostream>
int main() {
std::plus<int> add;
std::cout << add(1, 2) << std::endl;
std::minus<int> sub;
std::cout << sub(3, 2) << std::endl;
std::multiplies<int> mul;
std::cout << mul(2, 3) << std::endl;
std::divides<int> div;
std::cout << div(10, 3) << std::endl;
return 0;
}
在上面的示例中,我们使用 std::plus<int>
函数对象来相加两个整数,使用 std::minus<int>
函数对象来相减两个整数,以此类推。
2. 关系操作符
STL 也提供了多个关系操作符函数对象,如 less
、greater
、less_equal
、greater_equal
等。同样,也可以通过头文件 <functional>
导入。
#include <functional>
#include <iostream>
#include <string>
int main() {
std::less<int> less_than;
std::cout << less_than(1, 2) << std::endl;
std::greater<std::string> greater_than;
std::cout << greater_than("world", "hello") << std::endl;
std::less_equal<int> less_equal;
std::cout << less_equal(2, 3) << std::endl;
std::greater_equal<std::string> greater_equal;
std::cout << greater_equal("hello", "hello") << std::endl;
return 0;
}
在上面的示例中,我们使用 std::less<int>
函数对象来判断两个整数是否小于关系,使用 std::greater<std::string>
函数对象来判断两个字符串的大小关系,以此类推。
函数适配器
函数适配器是一种用于修改已有函数对象行为的对象。它可以帮助将一个函数适配到另一种类型,以便于执行某些操作。
STL 中提供了两种函数适配器,分别为 bind
和 mem_fn
。
1. bind 适配器
bind
适配器可以将一个函数对象用另外的参数进行绑定,生成一个新的函数对象,这个新的函数对象可以拥有原函数对象的一部分参数。得益于这种机制,我们可以通过 bind
适配器生成一个新的函数对象,同时使函数参数更加灵活。
#include <functional>
#include <iostream>
void func(int a, int b, int c) {
std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;
}
int main() {
auto f1 = std::bind(func, std::placeholders::_1, 2, std::placeholders::_2);
f1(10, 20);
auto f2 = std::bind(func, 1, std::placeholders::_2, std::placeholders::_1);
f2(100, 200);
return 0;
}
在上面的示例中,我们使用 std::bind
适配器生成了两个新的函数对象 f1
和 f2
。通过 std::placeholders::_1
、std::placeholders::_2
等占位符来指定新函数对象的参数绑定。
2. mem_fn 适配器
mem_fn
适配器可以将一个成员函数(即函数对象中的某个成员函数)进行适配,生成一个新的函数对象。使用 mem_fn
适配器的好处是可以将一个成员函数转换为普通函数对象,使得其可以被其他函数接受,并作为参数被传递。
#include <functional>
#include <iostream>
class Person {
public:
void sayHello(const std::string &name) {
std::cout << "Hello, " << name << "!" << std::endl;
}
};
int main() {
Person p;
auto f = std::mem_fn(&Person::sayHello);
f(p, "world");
return 0;
}
在上面的示例中,我们使用 std::mem_fn
适配器将 Person
类对象 p
中的 sayHello
成员函数适配成了普通函数对象 f
,然后使用该函数对象完成调用。由于 f
是一个普通函数对象,因此可以被其他函数接受,并作为参数被传递。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++:函数对象,STL提供的函数对象,函数适配器详解 - Python技术站