函数指针允许将函数作为参数传递或从函数返回函数

函数指针允许您将函数作为参数传递或从函数返回函数,从而实现灵活的行为和代码重用。它们在 C++ 编程中具有广泛的应用,包括回调、事件处理和算法选择。了解函数指针及其用法可以帮助您编写更模块化、可扩展和可定制的代码。以下是函数指针的一些实际应用示例:

  1. 回调函数:

    // 包含输入/输出流头文件,用于输出操作
    #include <iostream>// 使用 typedef 创建一个类型别名 CallbackFunc,表示一个函数指针
    // 该函数采用一个 int 类型的参数并返回 void
    typedef void (*CallbackFunc)(int);// 定义 performAction 函数,它采用一个回调函数和一个整数值作为参数
    void performAction(CallbackFunc callback, int value) {callback(value); // 调用回调函数并传递整数值
    }// 定义回调函数 printValue,它采用一个整数值作为参数
    void printValue(int value) {std::cout << "回调函数:值为 " << value << std::endl; // 打印整数值
    }// 主函数
    int main() {// 调用 performAction 函数,传入 printValue 函数作为回调函数和整数值 42performAction(printValue, 42);return 0; // 程序成功执行
    }
    

    在此示例中,我们定义了一个回调函数 printValue,它接受一个整数值并将其打印到控制台。然后,我们将 printValue 函数的地址作为回调函数传递给 performAction 函数。当调用 performAction 时,它使用提供的回调函数来打印值。

  2. 事件处理:

    // 包含输入/输出流头文件,用于输出操作
    #include <iostream>// 使用 typedef 创建一个类型别名 EventHandler,表示一个函数指针
    // 该函数采用一个 const std::string& 类型的参数并返回 void
    typedef void (*EventHandler)(const std::string&);// 定义 EventDispatcher 类
    class EventDispatcher {
    public:// 注册事件处理程序函数void registerEventHandler(EventHandler handler) {eventHandler = handler; // 将传入的处理程序函数存储在成员变量中}// 触发事件并调用注册的事件处理程序void triggerEvent(const std::string& message) {if (eventHandler) { // 如果注册了事件处理程序eventHandler(message); // 调用事件处理程序并传递消息}}private:// 事件处理程序函数指针EventHandler eventHandler;
    };// 定义事件处理程序函数
    void handleEvent(const std::string& message) {std::cout << "事件处理:消息为 " << message << std::endl; // 打印消息
    }// 主函数
    int main() {EventDispatcher dispatcher; // 创建 EventDispatcher 对象// 注册 handleEvent 函数作为事件处理程序dispatcher.registerEventHandler(handleEvent);// 触发事件并传递消息 "Hello, World!"dispatcher.triggerEvent("Hello, World!");return 0; // 程序成功执行
    }/***
    您提供的代码是一个使用事件处理和回调函数的简单示例。让我们逐步分解代码并解释它的工作原理:1. `#include <iostream>`:此行包含 iostream 头文件,用于输入/输出操作,例如使用 std::cout 进行输出。
    2. `typedef void (*EventHandler)(const std::string&)`:
    此行使用 typedef 创建了一个类型别名 EventHandler。它定义了一个函数指针类型,该函数采用一个 const std::string& 作为参数并返回 void。
    这意味着 EventHandler 是一个指向函数的指针,该函数可以处理 std::string 类型的事件。3. `class EventDispatcher {...} `:此代码定义了一个名为 EventDispatcher 的类。它具有两个公共成员函数:- `void registerEventHandler(EventHandler handler)`:此函数采用一个 EventHandler 类型的参数,并将其存储在 eventHandler 成员变量中。这允许您注册一个事件处理程序函数,该函数将在触发事件时调用。- `void triggerEvent(const std::string& message)`:此函数采用一个消息字符串作为参数,并检查 eventHandler 是否已被注册。如果是,它将调用注册的事件处理程序函数并传递消息。4. `void handleEvent(const std::string& message)`:
    此函数是事件处理程序函数。它采用一个消息字符串作为参数,并将其打印到控制台。5. `int main()`:这是主函数,程序执行从这里开始。- 一个 EventDispatcher 对象被创建并分配给 dispatcher。- 调用 dispatcher.registerEventHandler(handleEvent) 将 handleEvent 函数注册为事件处理程序。- 调用 dispatcher.triggerEvent("Hello, World!") 触发事件,传递消息 "Hello, World!"。- 事件处理程序函数 handleEvent 被调用,并打印消息。- 主函数返回 0,表示程序成功执行。总之,代码演示了如何事件和回调函数。 EventDispatcher 类允许您注册和触发事件,而 handleEvent 函数充当事件处理程序,响应触发的事件。
    这种设计模式在应用程序中很常见,因为它允许模块化和松散耦合,使您可以轻松添加或修改事件处理程序,而无需修改触发事件的代码。
    ***/

    在此示例中,我们定义了一个 EventDispatcher 类,它允许注册和触发事件。 EventHandler 函数指针类型用于定义事件处理函数。 handleEvent 函数被注册为事件处理程序,并在触发事件时调用。
     

    您提供的代码是一个使用事件处理和回调函数的简单示例。让我们逐步分解代码并解释它的工作原理:

    1. `#include <iostream>`:此行包含 iostream 头文件,用于输入/输出操作,例如使用 std::cout 进行输出。

    2. `typedef void (*EventHandler)(const std::string&)`:此行使用 typedef 创建了一个类型别名 EventHandler。它定义了一个函数指针类型,该函数采用一个 const std::string& 作为参数并返回 void。这意味着 EventHandler 是一个指向函数的指针,该函数可以处理 std::string 类型的事件。

    3. `class EventDispatcher {...} `:此代码定义了一个名为 EventDispatcher 的类。它具有两个公共成员函数:
       - `void registerEventHandler(EventHandler handler)`:此函数采用一个 EventHandler 类型的参数,并将其存储在 eventHandler 成员变量中。这允许您注册一个事件处理程序函数,该函数将在触发事件时调用。
       - `void triggerEvent(const std::string& message)`:此函数采用一个消息字符串作为参数,并检查 eventHandler 是否已被注册。如果是,它将调用注册的事件处理程序函数并传递消息。

    4. `void handleEvent(const std::string& message)`:此函数是事件处理程序函数。它采用一个消息字符串作为参数,并将其打印到控制台。

    5. `int main()`:这是主函数,程序执行从这里开始。
       - 一个 EventDispatcher 对象被创建并分配给 dispatcher。
       - 调用 dispatcher.registerEventHandler(handleEvent) 将 handleEvent 函数注册为事件处理程序。
       - 调用 dispatcher.triggerEvent("Hello, World!") 触发事件,传递消息 "Hello, World!"。
       - 事件处理程序函数 handleEvent 被调用,并打印消息。
       - 主函数返回 0,表示程序成功执行。

    总之,代码演示了如何事件和回调函数。 EventDispatcher 类允许您注册和触发事件,而 handleEvent 函数充当事件处理程序,响应触发的事件。这种设计模式在应用程序中很常见,因为它允许模块化和松散耦合,使您可以轻松添加或修改事件处理程序,而无需修改触发事件的代码。

  3. 算法选择:

    // 包含输入/输出流头文件,用于输出操作
    #include <iostream>// 使用 typedef 创建一个类型别名 ComparisonFunc,表示一个函数指针
    // 该函数采用两个 int 类型的参数并返回一个 int 类型的结果
    typedef int (*ComparisonFunc)(int, int);// 定义 findMax 函数,它采用一个整数数组、数组大小和一个比较函数作为参数
    // 该函数返回数组中的最大值
    int findMax(int array[], int size, ComparisonFunc comparator) {int maxVal = array[0]; // 初始化最大值为数组的第一个元素// 循环遍历数组中的每个元素for (int i = 1; i < size; ++i) {// 如果比较函数的结果大于 0,表示当前元素大于当前最大值if (comparator(array[i], maxVal) > 0) {maxVal = array[i]; // 更新最大值}}return maxVal; // 返回最大值
    }// 定义一个比较函数,用于升序比较
    int ascendingComparator(int a, int b) {return a - b; // 返回 a 和 b 的差值,用于比较大小
    }// 定义一个比较函数,用于降序比较
    int descendingComparator(int a, int b) {return b - a; // 返回 b 和 a 的差值,用于比较大小
    }// 主函数
    int main() {int arr[] = {5, 2, 8, 1, 9}; // 定义一个整数数组// 调用 findMax 函数,使用升序比较函数查找数组中的最大值int maxAscending = findMax(arr, 5, ascendingComparator);// 调用 findMax 函数,使用降序比较函数查找数组中的最大值int maxDescending = findMax(arr, 5, descendingComparator);// 输出结果std::cout << "升序最大值:" << maxAscending << std::endl;std::cout << "降序最大值:" << maxDescending << std::endl;return 0; // 程序成功执行
    }
    

    在此示例中,我们定义了一个 findMax 函数,它接受一个比较函数指针作为参数。根据提供的比较函数,它可以找到数组中的最大值。我们定义了两个比较函数 ascendingComparator 和 descendingComparator,并根据需要选择使用其中一个来找到最大值。

  4. GUI 库中的回调:
    GUI 库通常使用函数指针来实现回调机制。例如,在按钮单击事件处理程序中:

    #include <iostream>void buttonClickedCallback(int buttonId) {std::cout << "按钮 " << buttonId << " 被单击" << std::endl;
    }int main() {// 假设这是 GUI 库提供的函数registerButtonCallback(buttonClickedCallback);// ...return 0;
    }
    

    在此示例中,buttonClickedCallback 函数被注册为按钮单击事件的回调函数。当按钮被单击时,该回调函数被调用。

  5. 信号和槽机制:
    信号和槽机制是函数指针在 GUI 库中的另一个常见应用。例如,在 Qt 框架中:

    // 包含所有 Qt Widgets 模块所需的头文件
    #include <QtWidgets>// 定义槽函数,当按钮被点击时调用
    void slotFunction() {std::cout << "槽函数被调用" << std::endl; // 打印一条消息到控制台
    }// 主函数
    int main(int argc, char *argv[]) {QApplication app(argc, argv); // 创建 Qt 应用程序对象// 创建一个 QPushButton 对象,标签为 "点击我"QPushButton button("点击我");// 使用信号槽机制连接按钮的 clicked 信号和槽函数QObject::connect(&button, &QPushButton::clicked, &slotFunction);// 显示按钮button.show();// 启动事件循环,等待用户输入和信号处理return app.exec();
    }

    在此示例中,我们使用 QObject::connect 将按钮的 clicked 信号连接到 slotFunction 槽函数。当按钮被单击时,槽函数被调用。

这些示例展示了函数指针在 C++ 编程中的不同应用,包括回调函数、事件处理、算法选择和 GUI 库中的使用。函数指针允许您根据需要自定义和扩展代码的行为。

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

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

相关文章

OpenHarmony 实战开发——如何编译OpenHarmony自带APP

概述 OpenHarmony 的主干代码是开源社区的重要学习资源&#xff0c;对于想进行应用开发和熟悉 OpenHarmony 能力的同学主干代码是非常重要的资源&#xff0c;在主干代码的 applications 目录里聚集了很多原生的应用实现&#xff0c;那么如何编译这些代码就是我们这篇文章的主要…

信息系统架构设计方法_1.ADM架构开发方法

1.TOGAF概述 TOGAF&#xff08;The Open Group Architecture Framework&#xff0c;TOGAF&#xff09;是一种开放式企业架构框架标准&#xff0c;它为标准、方法论和企业架构专业人员之间的沟通提供一致性保障。 TOGAF由国际标准权威组织The Open Group制定。The Open Group于1…

[初学rust] 01_简单打印

print println!() 基本使用 直接输出一个字符串 println!("hello world");{} 占位符 println!("{}", "hello world");

Vue3项目打包部署到云服务器的Nginx中

文章目录 一、打包vue3项目二、dist文件夹上传到服务器三、改nginx配置文件Docker安装nginx 一、打包vue3项目 npm run build 二、dist文件夹上传到服务器 将dist文件夹放到docker安装的nginx中的html目录下 三、改nginx配置文件 然后重启nginx【改了配置文件重启nginx才能…

消息中间件Kafka(PHP版本)

小编最近需要用到消息中间件&#xff0c;有需要要复习一下以前的东西&#xff0c;有需要的自取&#xff0c;强调一点&#xff0c;如果真的想了解透彻&#xff0c;一定要动手&#xff0c;脑袋会了不代表就会写了 Kafka是由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅…

等保一体机能过三级等保吗?过等保无需再买安全设备如何做到?

等保一体机能过三级等保吗&#xff1f;过等保无需再买安全设备如何做到&#xff1f; 全云在线 2024-03-28 12:08 广东 尽管等保建设的标准是统一的&#xff0c;但由于不同行业和用户规模的差异&#xff0c;建设方案呈现出多样化的特点。 虽然重点行业过等保现象确实已经十分…

免费思维13招之八:跨行业思维

免费思维13招之八:跨行业思维 免费思维的另一大战略思维——跨行业型思维。 跨行业型思维有两种:一种是通过跨行业,把自己的产品免费掉,从而赚取其他行业的利润。另一种是通过跨行业,把别人的主流产品免费掉,从而增大自己产品的销量。 第一种,把自己的产品免费,从而赚…

Hadoop3.4.0 完全分布式集群 运行环境搭建 VMware Workstation 虚拟机 大数据系列 一

一 生产环境集群模式部署&#xff0c;需要多台主机&#xff0c;主机之间通过密钥相互访问. 1 配置如图 节点名字节点IP系统版本master11192.168.50.11centos 8.5slave12192.168.50.12centos 8.5slave13192.168.50.13centos 8.5 2 安装服务器 #先安装一台master11&#xff…

C++ 容器(四)——List操作

一、List定义 内部核心是双向链表结构&#xff1a; 1、list内部以双向链表形式存储元素&#xff0c;每个节点包含指向前一个节点和后一个节点的指针。 2、动态大小&#xff1a;list的大小可以根据需要动态增长或缩小&#xff0c;不需要预先指定容器的大小。 3、插入和删除效…

Kubernetes 监控管理

目录 1. Metrics Server2. Prometheus & Grafana3. cAdvisor4. 日志收集5. 告警与通知6. 最佳实践 Kubernetes 监控管理是确保集群稳定运行和应用服务质量的关键环节。它涉及收集、聚合、分析集群及其上运行的应用程序的各种指标和日志数据。 1. Metrics Server 作用&…

Kubernetes备份恢复

目录 1. etcd 备份与恢复2. Velero3. Kubernetes Checkpoint API4.最佳实践 在Kubernetes中&#xff0c;备份和恢复策略是确保集群和应用程序数据安全的关键部分。这包括了对集群元数据&#xff08;如部署、服务、PV/PVC定义等&#xff09;以及持久卷中的数据进行备份。 1. et…

Hadoop-未授权访问-内置配合命令执行RCE

一、Hadoop常见端口及配置文件 Hadoop中有多种端口&#xff0c;这些端口用于不同的服务和通信。以下是Hadoop中常见的端口以及它们的用途&#xff1a; NameNode Web界面端口 (默认: 9870)NameNode 对客户端服务端口 (默认: 8020)Secondary NameNode Web界面端口 (默认: 9868)…

图层的遮盖判定算法实现1

图层的判定算法实现1 1. 算法思路2. 增加图层类属性3. 修改图层工具类4. 置于灰色5. 调用比较置灰 图层的判定算法实现1 学习于bilibili 尚学堂官方 1. 算法思路 与它上方的那一层所有牌进行比较&#xff0c;是否有交集 有&#xff0c;则盖住了&#xff0c;显示灰色 没有&am…

GitLab CI/CD的原理及应用详解(五)

本系列文章简介&#xff1a; 在当今快速变化的软件开发环境中&#xff0c;持续集成&#xff08;Continuous Integration, CI&#xff09;和持续交付&#xff08;Continuous Delivery, CD&#xff09;已经成为提高软件开发效率、确保代码质量以及快速响应市场需求的重要手段。Gi…

Ubuntu20.4部署Cuda12.4

准备Ubuntu20.4 VM 安装Cuda12.4 1.进入如下界面安装安装Cuda12.4版本&#xff1a; CUDA Toolkit 12.4 Update 1 Downloads | NVIDIA Developerhttps://developer.nvidia.com/cuda-downloads?target_osLinux&target_archx86_64&DistributionUbuntu&target_vers…

MySQL软件安装基于压缩包

打开mysql官网网址 MySQL :: Download MySQL Community Server 本次针对版本8的安装包方式进行安装&#xff0c;下载成功后接下来对MySQL进行安装 下载后有一个以zip后缀结尾的压缩包文件 对于安装包方式安装&#xff0c;比起可视化安装省去了许多安装步骤&#xff0c;这里直接…

MLXtend,一个数据科学和机器学习Python库

MLxtend库简介 MLxtend 是一个 Python 库,提供了一系列用于机器学习的工具和辅助函数.它构建在 NumPy、SciPy 和 Matplotlib 之上,旨在为机器学习工程师和数据科学家提供更多的便利功能. 安装与使用 # 使用 pip 安装 MLxtend&#xff1a; pip install mlxtend在 Python 中导…

Python | Leetcode Python题解之第86题分隔链表

题目&#xff1a; 题解&#xff1a; class Solution:def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:sml_dummy, big_dummy ListNode(0), ListNode(0)sml, big sml_dummy, big_dummywhile head:if head.val < x:sml.next headsml sm…

C++ | Leetcode C++题解之第86题分隔链表

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode* partition(ListNode* head, int x) {ListNode* small new ListNode(0);ListNode* smallHead small;ListNode* large new ListNode(0);ListNode* largeHead large;while (head ! nullptr) {if (head-…

安卓模拟器怎么修改ip地址

最近很多老铁玩游戏的&#xff0c;想多开模拟器一个窗口一个IP&#xff0c;若模拟器窗口开多了&#xff0c;IP一样会受到限制&#xff0c;那么怎么更换自己电脑手机模拟器IP地址呢&#xff0c;今天就教大家一个修改模拟器IP地址的方法&#xff01;废话不多说&#xff0c;直接上…