C++11之std::function

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lixiaogang_theanswer/article/details/84781937

一. std::function 概述
std::function 是一种通用的多态函数包装器 。std::function 的实例可以存储、复制和调用任何可调用的目标——函数、lambda表达式、绑定表达式或其他函数对象,以及指向成员函数的指针和指向数据成员的指针(统称为“可调用对象”) 存储的可调用对象 称为 std::function 的目标。如果一个std::function 不包含目标,它就被称为空。调用空std::function的目标会导致std::bad_function_call异常被抛出。 [ 翻译自cppreference官网]

二. std::function 存在的意义
对于每一个可调用的对象,它都有自己的类型;很多时候,多个不同类型的可调用对象却拥有着相同的调用形式。在C++98中,通用方法是定义一个指向该“类型”的函数指针,以存放其函数的地址,并放在一个函数表中,在需要调用的地方,直接通过指针来进行使用。然而,此方法是有局限的,因为它要求“可调用对象”的类型相同才可。 正如前面所述, 拥有相同调用形式的多个可调用对象,其类型不相同,因此无法用一个函数指针来指向这些 。而std::function的出现解决了此棘手问题。因为std::function 是一个模板,实现了泛型化操作,所以即使“可调用对象”的类型不同也是可以的,只要保证其“调用形式”一样,即“函数返回类型、函数参数类型与函数参数个数相同”即可。

三. std::function 操作
在这里插入图片描述

result_type: 该function类型的可调用对象返回类型;argument_type、first_argument_type、second_argument_type在C++17中弃用,C++20中删除。

四. 示例
示例一: 采用函数指针形式,如预期一样,只能指向相同类型的可调用对象。

#include <functional>
#include <numeric>
#include <algorithm>
#include <functional>
#include <stdlib.h>
#include <iostream>
using namespace std;


typedef int (*pTr)(int,int);
//具体执行函数
int Func(const int a,const int b, pTr p)
{
    if(!p)
    {
        fprintf(stderr, "p is null.\n");
        return -1;
    }
    return p(a,b);
}


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


//重载了函数调用的函数对象
struct Sub
{
    int operator()(int a,int b)
    {
        return a-b;
    }
};


int main()
{
    int a = 1,b = 2;
    std::cout<<"result: "<<Func(a,b,add)<<std::endl;
    //std::cout<<"result: "<<Func(a,b,Sub());// error: cannot convert 'Sub' to 'pTr {aka int (*)(int, int)}' for argument '3' to 'int Func(int, int, pTr)'
    return 0;
}

打印结果:result: 3

示例二: 采用 C++11中的std::function函数模板
由于std::function是一个模板,因此在实例化std::function类型的时候,需要显示的表名其对象的调用形式,即在std::function后面追加一对尖括号"<>"来指定类型。如:std::function<int(int,int)> 。声明了该std::function类型能够接收2个int类型参数且返回int类型的可调用对象。


#include <functional>
#include <numeric>
#include <algorithm>
#include <functional>
#include <stdlib.h>
#include <iostream>
#include <map>
#include <assert.h>

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


//重载了函数调用的函数对象
struct Sub
{
    int operator()(int a,int b)
    {
        return a-b;
    }
};

//除法
class Div
{
public:
    static int div(const int a, const int b)
    {
        assert(b);
        return a/b;
    }
};

//乘法操作
auto Lam = [](int a,int b)->int{return a*b;};

int main()
{
    int a = 4, b = 2;
    std::function<int(int,int)> f1 = add;       //普通函数
    std::function<int(int,int)> f2 = Sub();     //重载了函数调用运算符的函数对象
    std::function<int(int,int)> f3 = Lam;       //lambada表达式
    std::function<int(int,int)> f4 = Div::div;  //类静态成员函数
    std::cout<<"f1:"<<f1(a,b)<<" ,"<<"f2:"<<f2(a,b)<<" ,"<<"f3:"<<f3(a,b)<<" ,"<<"f4:"<<f4(a,b)<<std::endl;
    return 0;
}

打印结果:
在这里插入图片描述

示例三. 调用一个空的std::function实例会抛出std::bad_function_call异常

#include <functional>
#include <numeric>
#include <algorithm>
#include <functional>
#include <stdlib.h>
#include <iostream>
#include <map>
#include <assert.h>
#include <exception>

int main()
{
   std::function<int(int)> f(nullptr); //显示的构造一个空的std::function
   try{
       f(10);
   }catch(const std::bad_function_call& e) {
       std::cout << e.what() << '\n';
   }
    return 0;
}

打印结果:bad_function_call

猜你喜欢

转载自blog.csdn.net/lixiaogang_theanswer/article/details/84781937