当前位置: 首页 > news >正文

C++看懂并使用-----回调函数

一)回调函数的定义
在 C++ 中,回调函数是一段作为参数传递给其他函数的可执行代码。它允许在一个函数内部的特定点调用外部定义的函数,以实现更灵活的功能。
回调函数(Callback Function)是一种通过函数指针或函数对象(在 C++ 中)实现的机制。简单来说,它是一段可被作为参数传递给其他函数的代码,并且在适当的时候(由接收该函数的函数决定)被调用。这就像是给别人你的电话号码,然后让他们在需要的时候打给你。
1)通过函数指针实现回调函数;
函数指针是指向函数的指针变量,其定义语法如下:
*返回类型 (指针变量名)(参数列表);

#include <iostream>
// 定义回调函数类型,它接受一个整数参数,返回一个整数
typedef int (*CallbackFunction)(int); 
// 函数,它接收一个回调函数作为参数,并对给定数值进行处理
int processValue(int num, CallbackFunction callback){return callback(num);
}
// 具体的回调函数,实现将输入数值加10的功能
int addTen(int num){return num + 10;
}
// 另一个具体的回调函数,实现将输入数值乘以2的功能
int multiplyByTwo(int num) {return num * 2;
}
int main() 
{int originalValue = 5;// 使用addTen作为回调函数进行处理int result1 = processValue(originalValue, addTen);std::cout << "使用addTen回调函数的结果: " << result1 << std::endl;// 使用multiplyByTwo作为回调函数进行处理int result2 = processValue(originalValue, multiplyByTwo);std::cout << "使用multiplyByTwo回调函数的结果: " << result2 << std::endl;return 0;
}

在这个示例中:
首先通过typedef定义了CallbackFunction类型,它代表一个函数指针类型,指向接受一个整数参数并返回一个整数的函数。
processValue函数接收一个整数和一个CallbackFunction类型的回调函数作为参数,它在内部调用传入的回调函数对给定数值进行处理,并返回处理后的结果。
addTen和multiplyByTwo是两个具体的回调函数实现,分别完成不同的数值处理逻辑。在main函数中,可以看到将不同的回调函数传递给processValue函数,从而实现不同的处理效果。

2)通过函数对象(仿函数)实现回调函数
函数对象是一个类,它重载了函数调用运算符 operator(),使得类的对象可以像函数一样被调用。例如:
示例二:容器元素处理的回调函数(使用函数对象)

#include <iostream>
#include <vector>
// 函数对象(仿函数)类,用于将容器中的元素翻倍
class DoubleElement 
{
public:void operator()(int& element) const {element *= 2;}
};
// 函数用于遍历容器,并对每个元素调用传入的回调函数进行处理
template <typename Container, typename Functor>
void processContainer(Container& container, Functor functor){for (auto& element : container){functor(element);}
}
int main() 
{std::vector<int> numbers = {1, 2, 3, 4, 5};std::cout << "处理前的容器元素: ";for (int num : numbers){std::cout << num << " ";}std::cout << std::endl;// 使用 DoubleElement 函数对象作为回调函数处理容器元素processContainer(numbers, DoubleElement());std::cout << "处理后的容器元素: ";for (int num : numbers) {std::cout << num << " ";}std::cout << std::endl;return 0;
}

在这个示例中:
DoubleElement 是一个函数对象类,通过重载 operator() 实现了将传入的整数引用类型的参数翻倍的功能,它可以作为回调函数使用。
processContainer 是一个模板函数,它接收一个容器和一个函数对象作为参数,在函数内部遍历容器中的元素,并调用传入的函数对象对每个元素进行处理。
3)事件处理中的回调函数(使用 std::function)

#include <iostream>
#include <functional>
// 定义一个简单的事件处理器类
class EventHandler 
{
public:// 使用 std::function 来存储不同类型的回调函数,这里的回调函数无参数,无返回值std::function<void()> onButtonClick;
};
int main() {EventHandler handler;handler.onButtonClick = []() {std::cout << "按钮被点击了!" << std::endl;};// 模拟按钮点击事件,调用存储的回调函数std::cout << "模拟触发按钮点击事件" << std::endl;handler.onButtonClick();return 0;
}

在这个示例中:
EventHandler 类中定义了 onButtonClick 成员变量,其类型为 std::function<void()>,用于存储在按钮点击时要执行的回调函数。
在 main 函数中,通过 lambda 表达式给 onButtonClick 赋值了一个具体的回调函数实现,当模拟按钮点击事件时,就会调用这个存储的回调函数来处理相应的操作。
这些示例展示了 C++ 回调函数在不同场景下的应用,通过回调函数可以让代码更加灵活、可复用和易于扩展。
4)基于类成员函数的回调函数(使用函数指针到类成员函数)

#include <iostream>
#include <vector>
// 定义一个简单的类
class Calculator 
{
public:int add(int a, int b) { return a + b; }int subtract(int a, int b) { return a - b; }
};
// 定义回调函数类型,指向Calculator类的成员函数,该成员函数接受两个整数参数,返回一个整数
typedef int (Calculator::*MemberCallback)(int, int); 
// 函数用于调用传入的类成员函数回调进行计算
int performOperation(int a, int b, Calculator& calculator, MemberCallback callback){return (calculator.*callback)(a, b);
}
int main() {Calculator myCalculator;int num1 = 10, num2 = 5;// 使用Calculator类的add成员函数作为回调进行计算int result1 = performOperation(num1, num2, myCalculator, &Calculator::add);std::cout << "使用add成员函数回调的结果: " << result1 << std::endl;// 使用Calculator类的subtract成员函数作为回调进行计算int result2 = performOperation(num1, num2, myCalculator, &Calculator::subtract);std::cout << "使用subtract成员函数回调的结果: " << result2 << std::endl;return 0;
}

此示例中:
先定义了Calculator类,包含add和subtract两个成员函数用于简单的算术运算。
通过typedef定义了MemberCallback类型,它是指向Calculator类成员函数的函数指针类型,这类成员函数接受两个整数参数并返回一个整数。
performOperation函数接收两个整数参数、一个Calculator类的对象以及一个MemberCallback类型的回调函数指针,在函数内部通过特定语法(calculator.*callback)(a, b)来调用传入的类成员函数回调进行相应的计算。在main函数中展示了如何使用不同的类成员函数作为回调来执行不同的运算操作。
5)数组元素处理回调函数

#include <iostream>
#include <vector>
// 回调函数类型定义,用于处理数组中的元素,无返回值
typedef void (*ArrayCallback)(int&); 
// 函数用于遍历数组,并对每个元素调用回调函数进行处理
void processArray(std::vector<int>& arr, ArrayCallback callback) 
{for (int& element : arr){callback(element);}
}
// 具体的回调函数,实现将数组元素值加1的功能
void incrementElement(int& num){num++;
}
int main(){std::vector<int> numbers = {1, 2, 3, 4, 5};std::cout << "处理前的数组: ";for (int num : numbers) {std::cout << num << " ";}std::cout << std::endl;// 使用incrementElement作为回调函数处理数组元素processArray(numbers, incrementElement);std::cout << "处理后的数组: ";for (int num : numbers){std::cout << num << " ";}std::cout << std::endl;return 0;
}

在这个示例里:
定义了ArrayCallback类型,它指向一个接受整数引用作为参数且返回类型为void的函数,适合用来处理数组元素并修改其值。
processArray函数接收一个整数向量和对应的回调函数作为参数,它遍历向量中的每个元素,并调用回调函数对元素进行处理。
incrementElement是一个具体的回调函数,实现对数组元素值加 1 的功能。在main函数中可以看到调用processArray函数并传入incrementElement回调函数后,数组元素都被相应地修改了。

相关文章:

C++看懂并使用-----回调函数

一&#xff09;回调函数的定义 在 C 中&#xff0c;回调函数是一段作为参数传递给其他函数的可执行代码。它允许在一个函数内部的特定点调用外部定义的函数&#xff0c;以实现更灵活的功能。 回调函数&#xff08;Callback Function&#xff09;是一种通过函数指针或函数对象&a…...

构建短视频矩阵生态体系开发分享

短视频矩阵系统模型的技术开发是一个综合性强、复杂度高的工程项目&#xff0c;它涵盖了广泛的技术选择与架构规划。以下是该项目开发过程中的关键步骤和核心考虑因素&#xff1a; 需求分析阶段&#xff1a; 明确目标用户群体及其需求&#xff0c;以确保系统设计的针对性和实…...

qt QGraphicsScale详解

1、概述 QGraphicsScale是Qt框架中提供的一个类&#xff0c;它提供了一种简单而灵活的方式在QGraphicsView框架中实现缩放变换。通过设置水平和垂直缩放因子、缩放中心点&#xff0c;可以创建各种缩放效果&#xff0c;提升用户界面的交互性和视觉吸引力。结合QPropertyAnimati…...

CAD 文件 批量转为PDF或批量打印

CAD 文件 批量转为PDF或批量打印&#xff0c;还是比较稳定的 1.需要本地安装CAD软件 2.通过 Everything 搜索工具搜索&#xff0c;DWG To PDF.pc3 &#xff0c;获取到文件目录 &#xff0c;替换到代码中&#xff0c; originalValue ACADPref.PrinterConfigPath \ r"C:…...

Java基础面试题16:简述Servlet的体系结构

Servlet 是 JavaEE 技术中的一大核心组件&#xff0c;它运行在服务器端&#xff0c;用于处理客户端的请求并生成响应。如果你想深入了解它的体系结构&#xff0c;下面会用通俗的语言带你一步步搞懂。 1. Servlet API&#xff1a;开发者和容器沟通的桥梁 Servlet API 是开发 S…...

Web开发基础学习——理解React组件中的根节点

Web开发基础学习系列文章目录 第一章 基础知识学习之理解React组件中的根节点 文章目录 Web开发基础学习系列文章目录前言一、根节点的概念二、示例解释总结 前言 在 React 应用中&#xff0c;根节点&#xff08;Root Node&#xff09;是指 React 组件树的起始点&#xff0c;…...

【人工智能】探索自然语言生成(NLG):用GPT生成文本

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 自然语言生成(Natural Language Generation, NLG)是自然语言处理(NLP)领域的重要分支,旨在生成符合语法和语义的自然语言文本。近年来,基于深度学习的生成式预训练模型(GPT)在NLG任务中取得了巨大…...

挑战用React封装100个组件【004】

项目地址 https://github.com/hismeyy/react-component-100 组件描述 组件适用于展示图片的地方&#xff0c;提供了small&#xff0c;medium&#xff0c;large三种大小。可以删除图片&#xff0c;也可以全屏预览图片。 样式展示 前置依赖 今天我们的这个挑战需要用用到了…...

vue elementui layout布局组件实现规则的弹性布局

背景&#xff1a;遇到在一个容器里&#xff0c;采用弹性盒布局的时候&#xff0c;如果元素个数改变&#xff0c;元素的排列会错乱。 解决方式 方式一&#xff1a;之前遇到的时候&#xff0c;是采用计算元素个数的方式&#xff0c;采用透明元素补齐的方式&#xff08;比如一个有…...

SpringBoot Web 开发请求参数

SpringBoot Web 开发请求参数 简单的 web 请求: @RestController public class HelloController {@RequestMapping("sayHello")public String sayHello(){System.out.println("Hello World");return "hello world";} }获取请求参数 简单参数…...

python7学习笔记-循环、迭代、pass

九九乘法表-while循环 right 1 while right < 9:left 1while left < right:print(f{left}x{right}{left * right},end\t)left 1print()right 1 # #效果&#xff1a; #1x11 #1x22 2x24 #1x33 2x36 3x39 #1x44 2x48 3x412 4x416 #1x55 2x510 3x515 4x520 5x525 #…...

LeetCode78:子集

链接&#xff1a;78. 子集 假设我们要求[1, 2, 3]的子集&#xff1a; 我们知道[1, 2]的子集是A&#xff1a; 而[1, 2, 3]就是比[1, 2]多了一个元素3&#xff1b;所以将3加入到上述A中的每个集合中&#xff0c;得到一个新集合B&#xff1a; 结论&#xff1a;[1, 2, 3]的子集就…...

Linux 安装scala

文章目录 Linux 安装scala下载环境变量配置 Linux 安装scala 前提linux需要已经安装好JDK&#xff08;JDK安装&#xff09;&#xff0c;Scala对JDK版本有明确的要求。通常&#xff0c;Scala的稳定版本要求JDK版本不低于1.8。例如&#xff0c;Scala 2.11.8和2.12.7版本都要求JD…...

重生之我在异世界学编程之C语言:深入指针篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文&#xff08;1&#xff09;内置数…...

linux centos7 yum命令失效

linux centos7 yum命令失效 Centos7使用yum命令失效&#xff0c;报错&#xff1a;Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infrastock error was 14: curl#6 - “Could not resolve host: mirrorlist.centos.or…...

mac访达打开终端

选择文件夹打开 选中文件夹&#xff0c;然后右键即可&#xff1a; 在当前文件夹打开 在访达的当前文件夹长按option键 左下角出现当前文件夹路径 右键即可打开终端...

【MySQL 进阶之路】索引的使用

5.索引的使用规则 在数据库管理系统&#xff08;DBMS&#xff09;中&#xff0c;索引是提高查询效率的关键机制之一。MySQL索引优化是指通过设计、调整和选择合适的索引策略&#xff0c;以提高数据库的查询性能和降低资源消耗。以下是一些关键的索引使用规则&#xff1a; 1. …...

网络编程相关 API 学习

目录 1. 网络编程中的基本概念 2. UDP 的 socket api 的使用 (1) DatagramSocket API (2) DatagramPacket API (3) InetSocketAddress API (4) 使用 UDP 的 socket api 3. TCP 的 socket api 的使用 (1) ServerSocket API (2) Socket API 1. 网络编程中的基本概念 客…...

python使用python-docx处理word

文章目录 一、python-docx简介二、基本使用1、新建与保存word2、写入Word&#xff08;1&#xff09;打开文档&#xff08;2&#xff09;添加标题&#xff08;3&#xff09;添加段落&#xff08;4&#xff09;添加文字块&#xff08;5&#xff09;添加图片&#xff08;6&#xf…...

【笔记2-1】ESP32:基于vscode的espidf插件的开发环境搭建

主要参考b站宸芯IOT老师的视频&#xff0c;记录自己的笔记&#xff0c;老师讲的主要是linux环境&#xff0c;但配置过程实在太多问题&#xff0c;就直接用windows环境了&#xff0c;老师也有讲一些windows的操作&#xff0c;只要代码会写&#xff0c;操作都还好&#xff0c;开发…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...