C++11中的std::function


先来看一个例子:

#include <iostream>

std::function<int(int, int)> func;

int add(int a, int b) {
    return a + b;
}

auto reduce = [](int a, int b) -> int { return a - b; };


struct Multi {
    int operator()(int a, int b) {
        return a * b;
    }
};

class Divide {
public:
    int operator()(int a,int b){
        if (b == 0){
            return 0;
        }
        return a /b;
    }
};

int main() {
    Multi multi;
    Divide divide;
    std::cout << multi(10,20) << std::endl;
    std::cout << divide(10,20) << std::endl;


    func = add;
    std::cout << func(1,2) << std::endl;

    func = reduce;
    std::cout << func(1,2) << std::endl;

    func = multi;
    std::cout << func(1,2) << std::endl;

    func = divide;
    std::cout << func(1,2) << std::endl;

    return 0;
}

在 C++11,引入了std::fucntion.

由于C++中定义方法的方式有很多(严格来说叫做可调用对象),在大型系统中传递对象和回调方法可能不是很方便.

因此引入了std::function,对各种可调用对象进行包装,以便于统一管理,这么说可能还是不直观,来分析一下.

int add(int a, int b) {
    return a + b;
}

auto reduce = [](int a, int b) -> int { return a - b; };


struct Multi {
    int operator()(int a, int b) {
        return a * b;
    }
};

class Divide {
public:
    int operator()(int a,int b){
        if (b == 0){
            return 0;
        }
        return a /b;
    }
};

上面几个方法定义的形式都是同一种:

int(int,int)

使用std:function<int(int,int)>就可以将这种形式的方法包装起来:

std::function<int(int, int)> func = add;
std::function<int(int, int)> func = reduce;
std::function<int(int, int)> func = multi;
std::function<int(int, int)> func = divide;

std::function是一个类模板,作用是包装可调用对象,可以包装除了类成员函数指针以外的所有可调用对象,它可以用统一的方式处理函数,函数对象,函数指针,并允许保存和延迟它们的执行.

定义的格式如下:

std::function<函数类型>

std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用.

可调用对象有下面这些:

  • 函数指针
  • 一个具有operator()成员函数的类的对象
  • 可被转换成函数指针的类对象
  • 一个类成员函数指针

普通的回调函数

再来说一下回调函数的问题,我们使用回调函数的步骤一般如下:

  1. 定义一个普通函数,作为回调函数
  2. 将回调函数的地址注册给调用者
  3. 调用者在适当的时刻通过函数指针调用回调函数.

实现方式如下:

typedef void(*callback)(std::string msg);

void log(std::string msg){
    std::cout << msg << std::endl;
}

void notifyFunc(callback f){
    f("Hello World");
}

int main() {
    notifyFunc(log);
    return 0;
}

std::function 作为回调函数

void logInfo(const std::string& msg){
    std::cout << msg << std::endl;
}

int main() {
    std::function<void(const std::string)> callbackFunc = logInfo;
    callbackFunc("Hello World");
    return 0;
}

文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
Flutter Engine编译和源码阅读 Flutter Engine编译和源码阅读
Flutter Engine的编译以及源码阅读其实挺简单的,只要按照官方文档的步骤来,一般都不会有什么问题.这里记录一下编译的流程,以及源码查看的一些配置和问题. 下载 下载depot_tools,并配置环境 git clone https
2020-12-07
下一篇 
C++中的typedef C++中的typedef
typedef几个用途: 定义类型的别名 typedef char* PCHAR typedef + struct 定义结构体,其实与别名本质上是一样的 typedef struct { char* name; int
2020-12-05