C++ function 可调用对象包装器、绑定器
文章目录
- C++ function 可调用对象包装器、绑定器
- 可调用对象
- 函数指针
- 函数对象(Functor):
- Lambda 表达式:
- 成员函数指针:
- 可调用对象包装器
- 主要特点
- 存储函数
- 存储 Lambda 表达式:
- 存储成员函数:
- 存储函数对象:
- 作为回调函数使用
- std::bind绑定器
- 主要特点
- 基本用法
可调用对象
在 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: 20return 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: 10return 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); // 输出: 8std::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: 30return 0;
}