类模版std::function是一种通用、多态的函数封装。std::function的实例可以对任何可以调用的目标实体进行存储、复制、和调用操作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。

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

自己实现function

#include <iostream>
#include <string>
using namespace std; template<typename T>
class MyFunction3 { }; template<typename Ty, typename A1>
class MyFunction3<Ty(A1)> { public:
typedef Ty(*pFunction)(A1);//定义一个函数指针,指针指向的函数返回类型是Ty,有1个函数参数
MyFunction3<Ty(A1)>(pFunction _pFunction) : _function(_pFunction) {
} Ty operator()(A1 arg1) {
return (*_function)(arg1);
} private:
pFunction _function;
}; template<typename Ty,typename A1,typename A2>
class MyFunction3<Ty(A1,A2)> { public: typedef Ty(*pFunction)(A1, A2);//定义一个函数指针,指针指向的函数返回类型是Ty,有两个函数参数
MyFunction3<Ty(A1, A2)>(pFunction _pFunction):_function(_pFunction) {
} Ty operator()(A1 arg1, A2 arg2) {
return (*_function)(arg1, arg2);
} private:
pFunction _function;
}; void showMes(string mes) {
cout << "showMes(string mes)=" << mes << endl;
} int sum1(int x, int y) {
cout << "sum1 "<<(x+y) << endl;
return x + y;
}
int sum2(int x, int y) {
cout << "sum2 " << (x + y) << endl;
return x + y;
} int main() { MyFunction3<int(int, int)> f1(sum1);
f1(20,30); MyFunction3<void(string)> f2(showMes);
f2("AAAA"); system("pause");
return 0;
}

上面代码我们实现了两个模板的部分特例化

class MyFunction3<Ty(A1)> 一个函数参数的

class MyFunction3<Ty(A1,A2)> 两个函数参数的

所以问题来了...三个参数,四个参数,五个参数等若干个参数的怎么办?

可以使用C++11 可变参数类型, 具体如下

#include <iostream>
#include <string>
using namespace std; template<typename T>
class MyFunction4 { }; template<typename R , typename... A >
class MyFunction4<R(A...)> { public:
typedef R(*PFUNCTION)(A...); MyFunction4<R(A...)>(PFUNCTION _p) : function(_p) {} R operator()(A... arg) {
return (*function)(arg...);
} private: PFUNCTION function;
}; void showMes1(string mes) {
cout << "showMes(string mes)=" << mes << endl;
} int sum11(int x, int y) {
cout << "sum11 " << (x + y) << endl;
return x + y;
}
int sum21(int x, int y) {
cout << "sum21 " << (x + y) << endl;
return x + y;
} int main() { MyFunction4<int(int, int)> f1(sum11);
f1(20, 30); MyFunction4<void(string)> f2(showMes1);
f2("AAAA"); system("pause");
return 0;
}

<五>function的实现原理的更多相关文章

  1. 2017-2018-2 《网络对抗技术》 20155322 第五周 Exp2 后门原理与实践

    #2017-2018-2 <网络对抗技术> 20155322 第五周 Exp2 后门原理与实践 [博客目录] 1-实践目标 1.1-实践介绍 1.2-实践内容 1.3-实践要求 2-实践过 ...

  2. [转帖]Docker五种存储驱动原理及应用场景和性能测试对比

    Docker五种存储驱动原理及应用场景和性能测试对比 来源:http://dockone.io/article/1513 作者: 陈爱珍 布道师@七牛云   Docker最开始采用AUFS作为文件系统 ...

  3. MySQL 第五篇:索引原理与慢查询优化

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

  4. SQL学习笔记五之MySQL索引原理与慢查询优化

    阅读目录 一 介绍 二 索引的原理 三 索引的数据结构 四 聚集索引与辅助索引 五 MySQL索引管理 六 测试索引 七 正确使用索引 八 联合索引与覆盖索引 九 查询优化神器-explain 十 慢 ...

  5. 集合总结五(Hashtable的实现原理)

    一.概述 上一篇介绍了Java8的HashMap,接下来准备介绍一下Hashtable. Hashtable可以说已经具有一定的历史了,现在也很少使用到Hashtable了,更多的是使用HashMap ...

  6. ASP.NET MVC学习(五)之MVC原理解析

    ASP.NET MVC 请求生命周期 生命周期步骤概览 当我们对ASP.NET MVC网站发出一个请求的时候,会发生5个主要步骤: 步骤1:创建RouteTable 当ASP.NET应用程序第一次启动 ...

  7. JavaScript学习总结(十五)——Function类

    在JavaScript中,函数其实是对象,每个函数都是Function类的实例,既然函数对象,那么就具有自己的属性和方法,因此,函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. 一.函数的 ...

  8. swift语言点评五-Function

    一.函数类型 Every function in Swift has a type, consisting of the function’s parameter types and return t ...

  9. Salesforce学习之路-developer篇(五)Aura组件原理及常用属性

    很喜欢曾经看到的一句话:以输出倒逼输入.以输出的形式强制自己学习,确实是高效的学习方式,真的很棒.以下仅为个人学习理解,如有错误,欢迎指出,共同学习. 1. 什么是Lightning Componen ...

  10. Libcurl笔记五_easy模式运行原理

    1, curl_easy_init内部调用Curl_open创建一个结构体SessionHandle(里面包含了所以curl使用的数据和指针)并初始化一些数据,然后返回将其作为给外侧使用的句柄CURL ...

随机推荐

  1. X-Pack:创建阈值检查警报

    简单的事情应该简单(Simple things should be simple),这是Elastic {ON} '17的主题之一,Elastics收到了许多关于使用简单易用的UI创建警报的请求.事实 ...

  2. 使用cnpm创建vue项目(含离线安装)

    # 全局安装淘宝cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org #升级 npm cnpm install npm ...

  3. Spring笔记四

    Spring-04 1.Spring整合Junit ①导入依赖 <!-- junit --> <dependency> <groupId>junit</gro ...

  4. NOI2014 洛谷P2114 起床困难综合征(位运算)

    呃...这道题算是noi中比较简单的题吧...... 众所周知,位运算是个好东西,它就是对应的位进行运算,跟其他的位没有关系. 我们要选取一个m值使最后的攻击力最大,对于这个m,从高位开始枚举,判断该 ...

  5. MasaFramework -- 异常处理

    前言 在程序设计中,我们会遇到各种各样的异常问题,一个异常处理不仅仅可以帮助开发者快速的定位问题,也可以给用户更好的使用体验,那么我们在AspNetCore项目中如何捕获以及处理异常呢? 而对应Asp ...

  6. 关于多个 Kubernetes 集群指标的采集操作

    简介 在使用观测云期间,有时需要针对一个工作空间接入多个 Kubernetes 集群指标,通过观测云提供的全局 Tag 的方式来进行区分,大大提高了效率.下面是我总结的操作步骤. 当集群中只有一个采集 ...

  7. 云计算_OpenStack

    部署方式-Fuel 注:部署失败且Fuel方式已过时. 部署方式-packstack 注:基于系统版本CentOS 7.9 2009部署 系统基本设置 设置静态IP=192.168.80.60 设置h ...

  8. Vue学习之--------组件自定义事件(绑定、解绑)(2022/8/21)

    文章目录 1.基础知识 2.代码实例 2.1 App.vue 2.2 school.vue 2.3 student.vue 3.测试效果(略) 4.实际应用(在组件化编码实战三的基础上改进) 4.1 ...

  9. 深入理解独占锁ReentrantLock类锁

    ReentrantLock介绍 [1]ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程 ...

  10. Charles基本功能

    Windows: 运行安装应用程序以在程序菜单中安装 Charles. Mac OS X: 通过双击解压缩下载文件,然后将 Charles 应用程序复制到 Applications 目录中. Linu ...