类模版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. Traefik2.X 版本 中 URL Rewrite 的使用

    文章转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247484594&idx=1&sn=becbe567 ...

  2. 关于kibana启动时有几个warning警告信息的解决办法

    启动kibana时会有几个warning信息,具体如下: 针对xpack这几个相关的,在kibana.yml文件中新增如下三个配置即可: # 注意:参数值至少32位,否则启动会报错提示 xpack.e ...

  3. 官方使用logstash同步Mysql数据表到ES的摘抄

    官方文档地址:https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html#plugins-inputs-jdbc ...

  4. Elasticsearch 趋势科技实战分享笔记

    文章转载自: https://mp.weixin.qq.com/s?__biz=MzI2NDY1MTA3OQ==&mid=2247484113&idx=1&sn=6c40d7f ...

  5. 云原生下基于K8S声明式GitOps持续部署工具ArgoCD实战-上

    @ 目录 概述 定义 工作原理 主要组件 核心概念 环境准备 概述 安装Kubekey 创建K8S 安装K9S OpenLB 安装ArgoCD 安装 ArgoCD CLI 从Git库中创建一个应用程序 ...

  6. SpringBoot课程学习(四)

    一.profile的多文档配置方式 1.profile文件方式:提供多个配置文件,每个代表一种环境 如: 1.application-dev.properties/yml 开发环境 2.applica ...

  7. 洛谷P2865 [USACO06NOV]Roadblocks G(次短路)

    一个次短路的问题,可以套用dijkstra求最短路的方法,用dis[0][i]表示最短路:dis[1][i]表示次短路,优先队列中存有最短路和次短路,然后每次找到一条道路对他进行判断,更新最短或次短路 ...

  8. Bing 广告平台迁移到 .net6

    原文链接 https://devblogs.microsoft.com/dotnet/bing-ads-campaign-platform-journey-to-dotnet-6/ 广告组件平台对于微 ...

  9. 【题解】CF1720C

    题意简述 给你一个 01 矩阵,每一次你可以在这个矩阵中找到一个 \(L\) 型,将它全部变成 0.\(L\) 型的定义是在一个 \(2\times2\) 矩阵中,除开一个角之外的图形,其中必须包含至 ...

  10. ES6 学习笔记(十一)迭代器和生成器函数

    1.前言 JavaScript提供了许多的方法来获取数组或者对象中的某个元素或者属性(迭代).从以前的for循环到之后的filter.map再到后来的for...in和for...of的迭代机制.只要 ...