C++ function 可调用对象包装器、绑定器
文章目录
可调用对象
在 C++ 中,可调用对象(Callable Object)是指可以像函数一样调用的对象。可调用对象包括但不限于以下几种类型
函数指针
- 指向函数的指针,可以用来调用函数。
void func(int x) {
std::cout << "Value: " << x << std::endl;
}
int main() {
void (*func_ptr)(int) = func;
func_ptr(10); // 调用函数
return 0;
}
函数对象(Functor):
- 具有
operator()
的类实例,可以像函数一样调用。
class Adder {
public:
int operator()(int a, int b) {
return a + b;
}
};
int main() {
Adder adder;
int result = adder(5, 3); // 调用函数对象
std::cout << "Result: " << result << std::endl;
return 0;
}
Lambda 表达式:
- 一种匿名函数,可以在代码中直接定义和使用。
int main() {
auto lambda = [](int a, int b) {
return a + b;
};
int result = lambda(5, 3); // 调用 Lambda 表达式
std::cout << "Result: " << result << std::endl;
return 0;
}
成员函数指针:
- 指向类成员函数的指针,需要与类实例一起使用。
class MyClass {
public:
void print(int x) {
std::cout << "Value: " << x << std::endl;
}
};
int main() {
MyClass obj;
void (MyClass::*print_ptr)(int) = MyClass::print;
(obj.*print_ptr)(10); // 调用成员函数
return 0;
}
可调用对象包装器
std::function
简介
std::function
是 C++ 标准库中的一个类模板,用于存储、管理和调用任何可调用目标(如函数、lambda 表达式、绑定表达式、函数对象等)。std::function
提供了一种统一的方式来处理各种可调用对象,使得代码更加灵活和通用。
主要特点
- 类型擦除:
std::function
可以存储不同类型和签名的可调用对象,通过类型擦除机制实现。- 例如,可以存储普通函数、成员函数、lambda 表达式、函数对象等。
- 灵活性:
- 可以动态地改变存储的可调用对象。
- 支持拷贝和移动语义。
- 可调用性:
- 存储的可调用对象可以通过
std::function
对象直接调用。
- 存储的可调用对象可以通过
- 空状态检查:
- 可以检查
std::function
是否为空(即是否存储了可调用对象)。
- 可以检查
基本用法:
#include <functional>
std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;
存储函数
void func(int x) {
std::cout << "Value: " << x << std::endl;
}
int main() {
std::function<void(int)> f = func;
f(10); // 调用函数
return 0;
}
存储 Lambda 表达式:
int main() {
std::function<void(int)> f = [](int x) {
std::cout << "Value: " << x << std::endl;
};
f(10); // 调用 Lambda 表达式
return 0;
}
存储成员函数:
#include <iostream>
#include <functional>
class MyClass {
public:
void print(int x) {
std::cout << "Value: " << x << std::endl;
}
};
int main() {
MyClass obj;
std::function<void(MyClass&, int)> f = &MyClass::print;
f(obj, 10); // 调用成员函数
return 0;
}
存储函数对象:
#include <iostream>
#include <functional>
class Adder {
public:
int operator()(int a, int b) {
return a + b;
}
};
int main() {
Adder adder;
std::function<int(int, int)> f = adder;
int result = f(5, 3); // 调用函数对象
std::cout << "Result: " << result << std::endl;
return 0;
}
作为回调函数使用
使用对象包装器std::function可以非常方便的将仿函数转换为一个函数指针,通过进行函数指针的传递,在其他函数的合适的位置就可以调用这个包装好的仿函数了。
另外,使用std::function作为函数的传入参数,可以将定义方式不相同的可调用对象进行统一的传递,这样大大增加了程序的灵活性
#include <iostream>
#include <functional>
using namespace std;
class A
{
public:
// 构造函数参数是一个包装器对象
A(const function<void()>& f) : callback(f)
{
}
void notify()
{
callback(); // 调用通过构造函数得到的函数指针
}
private:
function<void()> callback;
};
class B
{
public:
void operator()()
{
cout << "class B ==== > call back" << endl;
}
};
int main(void)
{
B b;
A a(b); // 仿函数通过包装器对象进行包装
a.notify();
return 0;
}
std::bind绑定器
std::bind
是 C++ 标准库中的一个函数模板,用于将一个可调用对象(如函数、成员函数、函数对象等)与其参数绑定在一起,生成一个新的可调用对象。这个新的可调用对象可以在稍后的时间点被调用,而不需要再次提供原始参数。
主要特点
- 参数绑定:
- 可以将部分或全部参数绑定到特定值。
- 绑定后的参数在调用时不再需要显式传递。
- 占位符:
- 使用占位符
_1
,_2
,_3
等来表示在调用时需要传递的实际参数位置。
- 使用占位符
- 灵活性:
- 可以绑定普通函数、成员函数、lambda 表达式、函数对象等。
- 延迟调用:
- 生成的可调用对象可以在任何时候被调用,适用于回调函数等场景。
基本用法
- 绑定普通函数:
#include <iostream>
#include <functional>
void func(int x, int y) {
std::cout << "x: " << x << ", y: " << y << std::endl;
}
int main() {
auto bound_func = std::bind(func, 10, std::placeholders::_1);
bound_func(20); // 输出: x: 10, y: 20
return 0;
}
- 绑定成员函数:
#include <iostream>
#include <functional>
class MyClass {
public:
void print(int x) {
std::cout << "Value: " << x << std::endl;
}
};
int main() {
MyClass obj;
auto bound_member = std::bind(&MyClass::print, &obj, std::placeholders::_1);
bound_member(10); // 输出: Value: 10
return 0;
}
- 绑定函数对象:
#include <iostream>
#include <functional>
class Adder {
public:
int operator()(int a, int b) {
return a + b;
}
};
int main() {
Adder adder;
auto bound_adder = std::bind(adder, 5, std::placeholders::_1);
int result = bound_adder(3); // 输出: 8
std::cout << "Result: " << result << std::endl;
return 0;
}
- 绑定多个参数:
#include <iostream>
#include <functional>
void func(int x, int y, int z) {
std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl;
}
int main() {
auto bound_func = std::bind(func, 10, std::placeholders::_1, std::placeholders::_2);
bound_func(20, 30); // 输出: x: 10, y: 20, z: 30
return 0;
}