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

函数指针允许您将函数作为参数传递或从函数返回函数,从而实现灵活的行为和代码重用。它们在 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 函数作为回调函数和整数值 42
        performAction(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 库中的使用。函数指针允许您根据需要自定义和扩展代码的行为。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yarn : 无法加载文件 C:\app\nodejs\node_global\yarn.ps1,因为在此系统上禁止运行脚本

系统运行yarn命令报错 解决办法&#xff1a; 一、点击电脑右下角的开始&#xff0c;菜单出来后&#xff0c;直接按键盘输入powerShell搜索&#xff0c;然后右键以管理员身份运行 二、以管理员运行后&#xff0c;会出现下面命令窗口 在窗口上执行&#xff1a;set-ExecutionPoli…

羊大师分析,羊奶健康生活的营养源泉

羊大师分析&#xff0c;羊奶健康生活的营养源泉 羊奶&#xff0c;作为一种古老的饮品&#xff0c;近年来因其独特的营养价值和健康益处而备受关注。今天&#xff0c;羊大师就来探讨一下羊奶与健康之间的紧密联系。 羊奶富含蛋白质、脂肪、维生素和矿物质等多种营养成分。羊奶…

哪家PMP培训机构比较优秀?

不同的培训机构在服务、收费和师资上会有一些差异&#xff0c;但基本都差不多。老师的授课方式对学习兴趣很重要&#xff0c;价格在3000-4000左右&#xff0c;选择中间价位比较好。服务也很关键&#xff0c;有的机构提供代报名和PDU等额外服务。关于机构排名的文章可以参考&…

InnoDB 事务处理机制

文章目录 前言1. 事务处理挑战1.1 事务机制处理的问题1.2 并发事务带来的问题 2. InnodDB 和 ACID 模型2.1 Innodb Buffer Pool2.2 Redo log2.3 Undo log2.4 应用案例 3. 隔离级别和锁机制3.1 事务隔离级别3.1.1 READ UNCOMMITTED3.1.2 READ COMMITTED3.1.3 REPEATABLE READ3.1…

CCF20181201——小明上学

CCF20181201——小明上学 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int r,y,g,n,k[101],t[101],sum0;cin>>r>>y>>g;cin>>n; for(int i0;i<n;i){cin>>k[i]>>t[i];if(k[i]0||k[i]1)sumt[i];…

Linux中的计划任务(crontab)详解

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Linux的起源与发展 2、什么是计划任务&#xf…

Xilinx RAM IP核的使用及注意事项

对于RAM IP核(Block Memory Generator核)的使用以及界面的配置介绍&#xff0c;文章RAM的使用介绍进行了较详细的说明&#xff0c;本文对RAM IP核使用中一些注意的地方加以说明。 文章目录 三种RAM的区别单端口RAM(Single-port RAM)简单双端口RAM(Simple Dual-port RAM)真双端…

供应链投毒预警 | 开源供应链投毒202404月报发布(含投毒案例分析)

概述 悬镜供应链安全情报中心通过持续监测全网主流开源软件仓库&#xff0c;结合程序动静态分析方式对潜在风险的开源组件包进行动态跟踪和捕获&#xff0c;发现大量的开源组件恶意包投毒攻击事件。在2024年4月份&#xff0c;悬镜供应链安全情报中心在NPM官方仓库&#xff08;…

翻译《The Old New Thing》- Stupid debugger tricks: Calling functions and methods

Stupid debugger tricks: Calling functions and methods - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20070427-00/?p27083 Raymond Chen 2007年04月27日 一个比较笨的调试技巧&#xff1a;调用函数和方法 在过去&#xff0c;如果你想在…

css+html 爱心❤

效果 代码实现 html <div class"main"><div class"aixin"></div></div>css .main {transform: rotate(-45deg);}.aixin {height: 100px;width: 100px;background-color: red;margin: auto;margin-top: 200px;position: relativ…

给app引导页说goodbye吧,皮之不存,毛将焉附。

有几个原因导致大部分创业者选择不开发独立的移动应用程序&#xff08;App&#xff09;&#xff1a; 成本和资源&#xff1a;开发和维护一个独立的移动应用程序需要投入大量的时间、资金和人力资源。对于创业公司来说&#xff0c;他们可能没有足够的资源来支持这样的开发和维护…

大数据性能测试怎么做?看完这篇终于懂了!

大数据性能测试的目的 1.大数据组件的性能回归&#xff0c;在版本升级的时候&#xff0c;进行新旧版本的性能比对。 2.在新版本/新的生产环境发布之后获取性能基线&#xff0c;建立可度量的参考标准&#xff0c;为其他测试场景或者调优过程提供对比参考。 3.在众多的发行版本…

【好书推荐-第十六期】《 LangChain技术解密:构建大模型应用的全景指南》(Github 6800+示例!)

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公众号&#xff1a;洲与AI。 &#x1f388; 本文专栏&#xff1a;本文收录…

【Flask 系统教程 6】进阶操作

Flask操作cookie 在 Flask 中操作 Cookie 是相对简单的。Cookie 是一种存储在用户计算机上的小型数据片段&#xff0c;由服务器发送到用户浏览器&#xff0c;然后在每次请求时由浏览器发送回服务器。在 Flask 中&#xff0c;你可以使用 request 对象来读取 cookie&#xff0c;…

【Maven】简介_下载安装

1.maven简介 项目管理工具项目对象模型 project object model (POM) 一个项目&#xff1a;清理、编译、测试、打包、发布、部署 1.1 为什么需要使用maven 组装机和品牌机的概念IDE &#xff08;集成开发环境&#xff09;不是万能的依赖大量的手工操作&#xff0c;编译、测试、…

npm install [Error]

npm install 依赖的时候报错 依赖版本问题的冲突&#xff0c;忽视即可 使用 npm install --legacy-peer-deps

个人写表格辅助软件

该软件作用 Excel 的辅助&#xff0c;可以执行excel不方便的操作&#xff0c;从excel复制数据到软件进行操作又复制回Excel。 下载软件地址 ,大小&#xff1a;65kb 点击下载 完整UI 列操作 右键单击列名弹出菜单 单元格操作 右键单击单元格弹出菜单 导航模式 每个操作都可以…

如何给实拍添加旋转模糊效果?视频模糊特效PR模板剪辑素材

PR特效模板&#xff0c;高级旋转模糊效果视频模板剪辑素材。 特征&#xff1a; After Effects 2019及以上兼容项目。 Premiere Pro 2021及以上兼容项目。 可用分辨率&#xff08;4K–HD–方形–移动&#xff09;。 不需要插件。 包括教程。 免费下载&#xff1a;https://prmu…

什么是电表智能抄表?

1.什么叫电表智能抄表 电表智能抄表&#xff0c;又被称为全自动读表系统&#xff0c;是一种利用通信网技术&#xff0c;如wifi网络、物联网技术或通信网络&#xff0c;全自动收集解决电能消耗数据信息的软件。与传统手动式抄水表方式相比&#xff0c;它大大提高了高效率&#…

Hadoop大数据应用技术复习题分析

文章目录 复习一一. 单选题二. 多选题三. 填空题 复习三一. 单选题 复习一 一. 单选题 (单选题)压缩速度由大到小snappy、LZO、gzip、bzip2&#xff0c;压缩比最大的是 A. snappy B. LZO C. gzip D. zip2 正确答案: D:zip2; 答案解析&#xff1a; 压缩率&#xff1a;zip2>…