C++语言中有几种可调用对象:函数、函数指针、lambda 表达式、bind 创建的对象以及重载了函数调用运算符的类。
和其他对象一样,可调用对象也有类型。两个不同类型的可调用对象可能共享同一种调用形式(call signature)。调用形式指明了调用返回的类型以及传递给调用的实参类型。一种调用形式对应一个函数类型,例如:int (int, int) 是一个函数类型,它接受两个int,返回一个int。
// 普通函数
int add(int a, int b){return a+b;}
// lambda表达式
auto mod = [](int a, int b){ return a % b;}
// 函数对象类
struct divide{
int operator()(int denominator, int divisor){
return denominator/divisor;
}
};
上面这些可调用对象分别对其参数执行了不同的算术运算,尽管它们的类型各不相同,但是共享同一种调用形式:
int(int ,int)
C++中可调用对象虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++11中提供了std::function和std::bind统一了可调用对象的各种操作。
std::function
std::function是C++标准库中的一个函数对象封装器,是一个类模板;它可以用来存储、复制和调用任何可调用对象(函数、函数指针、成员函数指针、lambda表达式等)。它提供了一种通用的方式来处理不同类型的可调用对象,并允许保存和延迟它们的执行,使得代码更加灵活和可扩展。
std::function的官方定义:
template<class R, class... Args>
function<R(Args...)>;
std::function的作用:
- 函数对象存储和调用:std::function可以用来存储不同类型的可调用对象,并且可以通过调用operator()来执行些对象。例如:
#include <iostream> #include <functional> int add(int a, int b) { return a + b; } int main() { std::function<int(int, int)> func = add; std::cout << func(1, 2) << std::endl; // 输出3 return 0; }
- 函数回调:std::function可以作为回调函数的类型,用于在特定事件发生时执行相应的操作。例如:
// 示例 1 #include <iostream> #include <functional> void foo() { std::cout << "Hello, world!" << std::endl; } void callFunc(std::function<void()> func) { func(); } int main() { std::function<void()> func = foo; callFunc(func); // 输出:Hello, world! return 0; } // 示例 2 #include <iostream> #include <functional> // 回调函数类型定义 typedef std::function<void(int)> CallbackFunc; // 回调函数 void callback(int value) { std::cout << "Callback function called with value: " << value << std::endl; } // 带参回调函数 void performCallback(int value, CallbackFunc callbackFunc) { std::cout << "Performing callback with value: " << value << std::endl; callbackFunc(value); } int main() { CallbackFunc func = callback; // 创建std::function对象,并绑定回调函数 performCallback(42, func); // 调用带参回调函数,传入回调函数对象 return 0; }
- 函数的延迟调用:std::function可以用于延迟调用函数,即在某个特定的时机才执行函数。例如:
#include <iostream> #include <functional> void delayedCall(const std::function<void()>& func) { // 延迟一段时间后执行函数 std::this_thread::sleep_for(std::chrono::seconds(1)); func(); } int main() { std::function<void()> func = []() { std::cout << "Delayed call" << std::endl; }; delayedCall(func); // 延迟1秒后输出:Delayed call return 0; }
std::bind
std::bind是C++标准库中的一个通用的函数适配器,是一个函数模板;创建一个可调用对象(函数对象或者函数指针)的绑定副本。它可以将函数的参数和调用方式进行绑定,生成一个新的可调用对象。并且可以延迟调用原始可调用对象,以及在需要时提供参数。
std::bind的官方定义:
template< class F, class... Args >
constexpr /*unspecified*/ bind( F&& f, Args&&... args );
std::bind的作用:
- 绑定函数的参数:可以将函数的部分参数绑定到指定的值,从而创建一个新的可调用对象。示例代码如下:
#include <iostream> #include <functional> void printSum(int a, int b) { std::cout << "Sum: " << a + b << std::endl; } int main() { auto printSumBind = std::bind(printSum, 10, std::placeholders::_1); printSumBind(20); // 输出:Sum: 30 return 0; }
- 绑定成员函数:可以将成员函数绑定到对象上,从而创建一个新的可调用对象。示例代码如下:
#include <iostream> #include <functional> class MyClass { public: void printMessage(const std::string& message) { std::cout << "Message: " << message << std::endl; } }; int main() { MyClass obj; auto printMessageBind = std::bind(&MyClass::printMessage, &obj, std::placeholders::_1); printMessageBind("Hello"); // 输出:Message: Hello return 0; }
- 函数指针的绑定:
#include <iostream> #include <functional> void printMessage(const std::string& message) { std::cout << "Message: " << message << std::endl; } int main() { auto printFunc = std::bind(printMessage, std::placeholders::_1); printFunc("Hello"); // 输出:Message: Hello return 0; }
- 函数对象的延迟调用:
#include <iostream> #include <functional> void printMessage(const std::string& message) { std::cout << "Message: " << message << std::endl; } int main() { auto printFunc = std::bind(printMessage, "Hello"); printFunc(); // 输出:Message: Hello return 0; }