C++ function 可调用对象包装器、绑定器

发布于:2024-12-09 ⋅ 阅读:(105) ⋅ 点赞:(0)

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 提供了一种统一的方式来处理各种可调用对象,使得代码更加灵活和通用。

主要特点
  1. 类型擦除:
    • std::function 可以存储不同类型和签名的可调用对象,通过类型擦除机制实现。
    • 例如,可以存储普通函数、成员函数、lambda 表达式、函数对象等。
  2. 灵活性:
    • 可以动态地改变存储的可调用对象。
    • 支持拷贝和移动语义。
  3. 可调用性:
    • 存储的可调用对象可以通过 std::function 对象直接调用。
  4. 空状态检查:
    • 可以检查 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. 占位符:
    • 使用占位符 _1, _2, _3 等来表示在调用时需要传递的实际参数位置。
  3. 灵活性:
    • 可以绑定普通函数、成员函数、lambda 表达式、函数对象等。
  4. 延迟调用:
    • 生成的可调用对象可以在任何时候被调用,适用于回调函数等场景。

基本用法

  1. 绑定普通函数:
#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;
}
  1. 绑定成员函数:
#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;
}
  1. 绑定函数对象:
#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;
}
  1. 绑定多个参数:
#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;
}

网站公告

今日签到

点亮在社区的每一天
去签到