C11 : 函数模板 std::function

目录

std::function

定义

实现原理

应用

注意事项


std::function

定义

类模板 std::function 是一种通用的、多态的函数封装

std::function 的实例可以对任何可以调用的目标实体进行存储、复制和调用操作,这些目标实体包括普通函数、Lambda 表达式、函数指针以及其他函数对象等。

std::function 对象是对 C++ 中现有的可调用实体的一种类型安全的包裹(像函数指针这类可调用实体,是类型不安全的)。

通常 std::function 是一个函数对象类,它包装其它任意的函数对象,被包装的函数对象具有类型为 T1, ..., TN 的 N 个参数,并且返回一个可转换到 R 类型的值。std::function 使用模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为 std::function。

实现原理

  1. 通过类的多态,即通过虚表来达到多态;

  2. 通过 C 语言的函数指针来实现;

单参数类模板,是 function<int(int)> 或 function<String(int)> 等格式的类模板:

template<class R, typename Arg0>
class myfunction<R(Arg0)>
{
    public:
        R operator()(Arg0 arg0)
        {
            return ...;
        }   
}

若实现可以调用不同的函数,模板函数首先要有一个指针,而且该指针具有多态性(C++ 通过基继承和虚表),故需要有一个基类指针使得所有继承于该类的子类成员,使用 virtual 关键字创建虚表:

template<class R, typename Arg0>
class myfunction<R(Arg0)> function 
{
    private:
        class __callbase{
            public:
                virtual R operator()(Arg0 arg0) = 0;
                virtual ~__callbase(){ }
        };

        __callbase *base_;

    public:
        R operator()(Arg0 arg0){
            return (*__callbase)(arg0);
    }
};

实现子类:

class myfunction<R(Arg0)> function{
    private:
        template<typename F>
        class __callable : public __callbase {
            public:
                // 增加指向赋值给 function 类的函数指针或函数类对象
                callable(F functor)
                    : functor(functor){ }
                // 指向后重载操作符进行直接调用
                virtual R operatr()(Arg0 arg0){
                    return functor(arg0);
                }
            private:
                // 指向具体的函数或函数类对象,由模板推导
                F functor;
        };
    public:
        template<typename F>
        myfunction(F f):base_(new __callable<F>(f)){
        }

        ~myfunction(){
            if(base_){
                delete base_;
                base_ = nullptr;
            }
        }
};

应用

通过 std::function 对 C++ 中各种可调用实体(普通函数、Lambda 表达式、函数指针、 仿函数以及其它函数对象等)的封装,形成一个新的可调用的、统一的 std::function 对象。

#include <functional>
#include <iostream>
using namespace std;

std::function<int(int)> Functional;


int TestFunc(int a){ return a;}// 普通函数

auto lambdaFn = [](int a)->int{ return a; };// Lambda表达式

class Functor{ // 仿函数(functor)
 public:
    int operator()(int a){return a;}
};

class TestClass{
 public:
    int ClassMember(int a) { return a; }// 1.类成员函数
    static int StaticMember(int a) { return a; }// 2.类静态函数
}; 


int main()
{

    // 普通函数
    Functional = TestFunc;
    int result = Functional(10);
    cout << "普通函数:"<< result << endl;


    // Lambda表达式
    Functional = lambdaFn;
    result = Functional(20);
    cout << "Lambda表达式:"<< result << endl;


    // 仿函数
    Functor testFunctor;
    Functional = testFunctor;
    result = Functional(30);
    cout << "仿函数:"<< result << endl;

    // 类成员函数
    TestClass testObj;
    Functional = std::bind(&TestClass::ClassMember, testObj
                    , std::placeholders::_1);
    result = Functional(40);
    cout << "类成员函数:"<< result << endl;


    // 类静态函数
    Functional = TestClass::StaticMember;
    result = Functional(50);
    cout << "类静态函数:"<< result << endl;
    return 0;

}

注意事项

  • 关于可调用实体转换为 std::function 对象需要遵守以下两条原则:

    • 转换后的 std::function 对象的参数能转换为可调用实体的参数;

    • 可调用实体的返回值能转换为 std::function 对象的返回值。

  • std::function 对象最大的用处就是在实现函数回调,需要注意,它不能被用来检查相等或者不相等,但是可以与 NULL 或者 nullptr 进行比较

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值