function 包装器 ——C++新特性(二)

文章目录

  • 包装器
    • function
    • 包装器可以包装可调用对象
    • 其他使用示例

🎖  博主的CSDN主页:Ryan.Alaskan Malamute
📜 博主的代码仓库主页 [ Gitee ]:@ryanala      [GitHub]: Ryan-Ala

包装器

function

使用 function包装器需要包含头文件 functional

#include<functional>

function是一种函数包装器,也叫做适配器。它可以对可调用对象进行包装,本质就是一个类模板

function类模板的原型如下

template <class T> function;     // undefined
template <class Ret, class... Args>   //第一个Ref 是返回值类型,后面是可调用对象的参数
class function<Ret(Args...)>;
  • 第一个Ref 是返回值类型
  • … Args 是可调用对象的参数

详细解释:

  • 该代码定义了一个模板类函数,该类接受一个或多个类型参数。
  • 第一行是一个不完整的声明,因为没有指定函数类型参数的具体类型,因此它是未定义的。
  • 第二行定义了一个模板类 function,它有一个类型参数Ret和一个变长模板参数Args,表示返回值类型和函数参数类型
  • 这个模板类的具体实现是针对函数类型 Ret(Args…)的。也就是说,这个模板类可以用来存储任意类型为Ret(Args…)的函数指针、函数对象等。
  • function包装器可以对可调用对象进行包装,包括函数指针(函数名)、仿函数(函数对象)、lambda表达式、类的成员函数等

包装器可以包装可调用对象

function解决可调用对象的类型问题,把可调用对象统一包装起来,存放到vector,map中去。
function主要可以包装下面三大类:

  1. 函数指针

    class A
    {static func_1(int x,int y){}   //包装成员函数需要加类域func_2(int x,int y){}
    }
    
  • 静态成员函数:取出静态成员函数的地址时,需要通过类名,但&不是必须的;
  • 非静态成员函数:取出非静态成员函数的地址时,需要通过类名,但&是必须的。非静态成员函数的第一个参数是this指针(它是隐藏的),因此在包装时需要指明第一个形参的类型为类的类型。
    • 包装类内静态函数

      类的静态函数没有 this 指针,只要正确的取地址包装即可,当然也可以不取地址&,直接加上类域也是可以的 function<int(int,int)> f1 = A::func_1

      class A
      {static func_1(int x,int y){}   func_2(int x,int y){}
      }function<int(int,int)> f1 = &A::func_1;  // 需要域名加取地址 同时该成员函数必须是静态的
      f1(1,2);
      
    • 包装类内非静态函数

      1. 方式1:传入一个对象的指针 >> function<int(A* , int , int )>

        非静态成员函数含有 this 指针,此时需要传一个对象的指针,在调用时内部就会使用该指针去调用函数

        注意:不可以使用 临时对象 因为临时对象时又指无法对临时对象取地址

        class A
        {static func_1(int x,int y){} func_2(int x,int y){}
        }int main()
        {function<int(A* ,int,int)> f2 = &A::func_2;   //非静态成员函数有一个隐含的this指针A new_A;    f2(&A,1,2);   //底层是用传过去的指针调用成员函数//注意: 这里不能使用临时对象,临时对象是右值,无法取地址f2(A(),1,2);  //错误的
        }
        
      2. 方式2:传入对象 >> function<int(A ,int , int )>

        或者直接传入一个对象,那么底层会使用这个对象去调用该函数

        class A
        {static func_1(int x,int y){} func_2(int x,int y){}
        }int main()
        {function<int(A ,int,int)> f2 = &A::func_2;f2(A(),1,2);  //正确的//底层使用对象去调用这个 函数指针
        }    
        
      3. bind 绑定(非 socket 编程的 bind ,这两个是老婆和老婆饼的关系)

        使用bind对函数进行处理将某些参数写死,后续调用时也就不需要传入对象或者对象的指针了 ,对于bind后续还会进行讲解。

        using namespace std::placeholders;
        // 绑定对象
        function<int(A ,int,int)> f2 = bind(&A::func_2,A(),placeholders::_1,placeholders::_2);
        f2(1,2);  //使用绑定将某些参数写死//绑定指针
        A a;
        function<int(A* ,int,int)> f2 = bind(&A::func_2,&a,placeholders::_1,placeholders::_2);
        f2(1,2);  //使用绑定将某些参数写死
        
  1. 仿函数

    function包装器也可以用来包装仿函数,不过初始化时要加上括号Swap(),因为这里必须是可调用对象

    示例:

    struct Swap
    {void operator()(int& r1, int& r2){	// .......}
    };function<void(int&, int&)> f2 = Swap();
    f2(x, y);
    
  2. lambda

    function包装器也可以包装Lambda表达式,这种方式代码较为简短,是一种非常常用的方式

    auto swaplambda = [](int& r1, int& r2) {int tmp = r1;r1 = r2;r2 = tmp;};function<void(int&, int&)> f3 = swaplambda;
    f3(x, y);
    

其他使用示例

int main()
{map<string, function<void(int&, int&)>> cmdOP = {{"函数指针", swap_func},{"仿函数", Swap()},{"lambda", swaplambda},};cmdOP["函数指针"](x, y);cout << x << " " << y << endl << endl;cmdOP["仿函数"](x, y);cout << x << " " << y << endl << endl;cmdOP["lambda"](x, y);cout << x << " " << y << endl << endl;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/803795.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

身份证二、三、四要素实名认证接口、C#开发示例

在瞬息万变的网络时空&#xff0c;每一次点击&#xff0c;每一份交易都离不开对“你是谁”的确认。想象一下&#xff0c;当我们畅游在网络的海洋中&#xff0c;无论是注册心仪已久的APP还是在线办理重要的业务&#xff0c;甚至是在虚拟世界中结交新朋友等活动时&#xff0c;只需…

Selenium+Chrome Driver 爬取搜狐页面信息

进行selenium包和chromedriver驱动的安装 安装selenium包 在命令行或者anaconda prompt 中输入 pip install Selenium 安装 chromedriver 先查看chrome浏览器的版本 这里是 123.0.6312.106 版 然后在http://npm.taobao.org/mirrors/chromedriver/或者https://googlechrom…

EasyPOI复杂表格导入

EasyPOI复杂表格导入 多表头数据导入方式一导入表格实体类文件导入代码测试结果 方式二导入表格实体类文件导入代码测试结果 总结 设置表格从哪行读取表格内容 多表头数据导入 方式一 导入的表格样式如下 导入表格实体类 package com.demo.entity;import cn.afterturn.eas…

基于令牌桶算法对高并发接口的优化

业务背景 项目中有一个抽奖接口&#xff0c;此接口需要处理高并发问题以及使用脚本作弊的问题。 本文主要探讨如何最大程度地减少脚本作弊行为对抽奖业务的影响。 设计思路 如何减少脚本作弊行为对抽奖业务的影响 使用令牌桶算法&#xff0c;对频率过高的用户请求进行拦截 …

pdffactory pro 8注册码序列号下载 附教程

PdfFactory Pro可以说是一款行业专业且技术领先的的PDF虚拟打印机软件。其不仅占用系统内存小巧&#xff0c;功能强大&#xff0c;可支持用户无需使用Acrobat来创建Adobe PDF即可以进行PDF组件的创建和打印。同时&#xff0c;现在全新的PdfFactory Pro 8也正式上线来袭&#xf…

(源码+部署+讲解)基于Spring Boot + Vue编程学习平台的设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31f;…

Hadoop简介

Hadoop 1、 Hadoop的介绍 Hadoop最早起源于Nutch。Nutch的设计目标是构建一个大型的全网搜索引擎&#xff0c;包括网页抓取、索引、查询等功能&#xff0c;但随着抓取网页数量的增加&#xff0c;遇到了严重的可扩展性问题——如何解决数十亿网页的存储和索引问题。2003年、20…

【数据结构】考研真题攻克与重点知识点剖析 - 第 7 篇:查找

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

开源铱塔切换MySQL数据库启动报异常

1.错误日志&#xff1a; 铱塔切换数据库配置为MySQL之后&#xff0c;启动后报错如下&#xff1a; SqlExceptionHelper - Table iotkit.task_info doesnt exist SqlExceptionHelper - Table iotkit.rule_info doesnt exist SqlExceptionHelper - Table iotkit.device_info does…

(WSI分类)WSI分类文献小综述 2024

2024的WSI分类。 Multiple Instance Learning Framework with Masked Hard Instance Mining for Whole Slide Image Classification &#xff08;ICCV2024&#xff09; 由于阳性组织只占 Gi- gapixel WSI 的一小部分&#xff0c;因此现有的 MIL 方法直观上侧重于通过注意力机…

Redis的常见命令

单线程&#xff1a;每个命令具备原子性 低延迟&#xff0c;速度快&#xff08;基于内存、IO多路复用、良好的编码&#xff09; 支持数据持久化 支持主从集群、分片集群 支持多语言客户端 2.Redis数据库介绍 Redis是一个key-value的数据库&#xff0c;key一般是String类型…

(源码+部署+讲解)基于Spring Boot + Vue的车位租赁系统设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31f;…

Apache Incubator Answer 本地开发部署

文章目录 简介Github文档插件部署 Answer开发环境编译项目初始化项目运行项目 简介 一款适合任何团队的问答平台软件。 Apache Incubator Answer是一个开源项目&#xff0c;它是一个用于构建和部署问答系统的框架。该项目是Apache软件基金会的孵化器项目&#xff0c;提供一个…

Nginx流媒体服务器RTMP直播同步录像

目录 一、环境 1、以下见往期文章 2、ffmpeg支持 二、建立录像路径

vscode 关键字记录

vscode 关键字记录&#xff1a; ${workspaceFolder}&#xff1a;当前工作区&#xff08;Workspace&#xff09;的根目录路径。${file}&#xff1a;当前打开文件的路径。如a/b/c/test.cpp。${fileDirname}&#xff1a;当前打开文件的目录路径。比如文件 test.cpp 位于 a/b/c&am…

自动驾驶中的传感器融合算法

目录 引言 一、传感器融合算法步骤 二、卡尔曼滤波 (Kalman Filter) 1. 卡尔曼滤波的原理 1.1. 预测步骤&#xff08;Predict&#xff09; 1.2. 更新步骤&#xff08;Update&#xff09; 2. 卡尔曼滤波在自动驾驶中的应用 2.1. 位置和姿态估计 2.2. 目标跟踪和感知 2…

【centos】Redis离线安装配置教程

Linux 离线安装Redis配置教程 一、下载二、安装redis三、设置redis开机自启&#xff0c;并且添加到系统服务四、gcc安装 redis官网地址&#xff1a;https://redis.io/ 一、下载 【点击进入下载地址&#xff1a;http://download.redis.io/releases/】选择安装包&#xff1a;re…

uniapp 地图分幅网格生成 小程序基于map组件

// 获取小数部分 const fractional function(x) {x Math.abs(x);return x - Math.floor(x); } const formatInt function(x, len) {let result x;len len - result.length;while (len > 0) {result 0 result;len--;}return result; }/*** 创建标准分幅网格* param …

STM32学习和实践笔记(6):自己进行时钟配置的思路

在《STM32学习和实践笔记&#xff08;4&#xff09;: 分析和理解GPIO_InitTypeDef GPIO_InitStructure (d)-CSDN博客》 中&#xff0c;我了解到&#xff0c;在程序执行我们写的main函数之前&#xff0c;实际上先执行了一个汇编语言所写的启动文件&#xff0c;以完成相应的初始…

Android 自定义解析html标签

用来解析类如下面代码里 html 标签样式. <span style"color: rgb(64, 169, 255);">文字内容</span> <span style"color: rgb(64, 169, 255); font-size: 16px;"><strong>文字</strong></span> 使用: val str htm…