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

C语言学习细节|C语言面向对象编程!函数指针如何正确使用

文章目录

  • 1.函数指针定义
  • 2.格式
  • 3.应用
    • 回调函数
    • 动态函数调用
    • 函数的间接调用
  • 4.结构体与函数指针结合

1.函数指针定义

函数指针就是一个指向函数的指针变量,与指向数据的指针不同,函数指针保存的是函数的地址,这使得程序可以动态地调用不同的函数,而无需在编译时确定具体的函数。可以在程序运行时动态得传递和调用不同的函数

2.格式

函数指针的声明格式为:

返回类型(*变量名)(参数列表),其中

例如,如果你有一个返回 int 类型并接受两个 int 类型参数的函数,你可以这样声明指向这种函数的指针:

int (*funcPtr)(int, int);

3.应用

函数指针在C语言中扮演着极其重要的角色,特别是在需要动态决定函数调用时。下面是三个具体的应用场景:

回调函数

在C语言中,回调函数通常用于实现基于事件的编程。例如,在一个图形用户界面库中,可能需要允许用户定义当按钮被点击时执行的动作。以下是一个简单的例子,展示了如何在一个假设的GUI库中使用回调函数来处理按钮点击事件:

#include <stdio.h>//定义函数指针
typedef void (*ButtonClickHandler)();//定义Button结构体
typedef struct Button {char* label; //函数名ButtonClickHandler onClick; //回调函数
} Button;//绑定回调函数
void buttonClick(Button* button) {if (button->onClick != NULL) {printf("Button '%s' clicked.\n", button->label);button->onClick();}
}//具体执行的函数
void handleExit() {printf("Exiting application...\n");
}int main() {Button exitButton = {"Exit", handleExit};buttonClick(&exitButton);return 0;
}

在这个例子中,Button 结构体包含了一个成员 onClick,这是一个指向函数的指针。当按钮被“点击”时(在这个例子中是通过调用 buttonClick 函数模拟),如果设置了 onClick 回调,它就会被调用。

动态函数调用

函数指针允许根据程序的状态或用户的输入动态调用不同的函数。例如,在一个简单的命令行计算器应用中,用户的选择可以决定调用哪个数学运算函数:

#include <stdio.h>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int main() {int (*operation)(int, int);char operator;int x = 5, y = 3;printf("Enter operation (+ or -): ");scanf(" %c", &operator);switch (operator) {case '+':operation = add;break;case '-':operation = subtract;break;default:printf("Invalid operation\n");return 1;}printf("Result: %d\n", operation(x, y));return 0;
}

函数的间接调用

函数的间接调用通常用于实现插件架构,其中函数可以在运行时加载和调用。在下面的例子中,我们模拟这种结构,其中函数指针数组用于调用一系列操作:

#include <stdio.h>void start() {printf("Starting the engine...\n");
}void stop() {printf("Stopping the engine...\n");
}void restart() {printf("Restarting the engine...\n");
}int main() {void (*operations[3])() = {start, stop, restart};for (int i = 0; i < 3; i++) {operations[i]();}return 0;
}

在这个例子中,我们定义了一个函数指针数组 operations,其中包含三个不同的操作:启动、停止和重启。通过遍历数组,我们可以间接调用这些函数。

4.结构体与函数指针结合

在C语言中,结构体与函数指针结合使用可以模拟面向对象编程中的类和方法。结构体可以包含指向函数的指针,允许结构体"实例"具有操作这些数据的"方法"。这是实现模块化和封装设计的一种方式。

例如,可以定义一个表示几何形状的结构体,该结构体包括函数指针,用于计算面积和周长:

typedef struct Shape {int (*getArea)(struct Shape*);int (*getPerimeter)(struct Shape*);int width;int height;
} Shape;int rectangleArea(Shape* s) {return s->width * s->height;
}int rectanglePerimeter(Shape* s) {return 2 * (s->width + s->height);
}void createRectangle(Shape *s, int width, int height) {s->width = width;s->height = height;s->getArea = rectangleArea;s->getPerimeter = rectanglePerimeter;
}int main() {Shape rect;createRectangle(&rect, 5, 10);printf("Area: %d\n", rect.getArea(&rect));printf("Perimeter: %d\n", rect.getPerimeter(&rect));return 0;
}

在这个例子中,Shape 结构体模仿了一个简单的"类",其中包含数据成员(宽度和高度)和作为其"方法"的函数指针。这种方式在设计需要封装数据和功能的模块时非常有用。

文章结构上参考了B站up主:【五分钟解决方案】函数指针如何正确使用
算是终于弄明白了函数指针了,至于指针函数,就把它理解为返回一个指针的函数,其实和别的函数没有任何区别,唯一需要注意的就是别返回一个临时变量的指针即可。
在一个在C++中往往会使用function和bind来实现,代码更加简洁优雅直观
扩展阅读:
C++语法|可调用对象与function类型
C++语法|bind和function解析并实现一个简易线程池
C++语法|bind1st和bind2nd的用法

相关文章:

C语言学习细节|C语言面向对象编程!函数指针如何正确使用

文章目录 1.函数指针定义2.格式3.应用回调函数动态函数调用函数的间接调用 4.结构体与函数指针结合 1.函数指针定义 函数指针就是一个指向函数的指针变量&#xff0c;与指向数据的指针不同&#xff0c;函数指针保存的是函数的地址&#xff0c;这使得程序可以动态地调用不同的函…...

C语言简要(一)

总得让她开心吧 helloworld #include <stdio.h>int main() {printf("hello world!\n");return 0; } 程序框架 #include <stdio.h> int main {return 0; }输出 printf("hello world!\n"); "里面的内容叫做“字符串”&#xff0c;prin…...

那些年我与c++的叫板(一)--string类自实现

引子&#xff1a;我们学习了c中的string类&#xff0c;那我们能不能像以前数据结构一样自己实现string类呢&#xff1f;以下是cplusplus下的string类&#xff0c;我们参考参考&#xff01; 废话不多说&#xff0c;直接代码实现&#xff1a;&#xff08;注意函数之间的复用&…...

二刷算法训练营Day08 | 字符串(1/2)

今日任务&#xff1a; 344.反转字符串 541. 反转字符串II卡码网&#xff1a;54.替换数字 151.翻转字符串里的单词卡码网&#xff1a;55.右旋转字符串 详细布置&#xff1a; 1. 344. 反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 …...

使用高防IP是应对网络安全的重要措施

使用高防IP&#xff08;High Defense IP&#xff09;在现代网络环境中显得尤为重要&#xff0c;这主要源于以下几个方面的原因&#xff1a; 一、网络安全形势严峻 随着互联网的快速发展&#xff0c;网络安全问题日益突出。各种网络攻击手段层出不穷&#xff0c;如分布式拒绝服…...

代码随想录-算法训练营day40【动态规划03:整数拆分、不同的二叉搜索树】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第九章 动态规划part03● 343.整数拆分 ● 096.不同的二叉搜索树 详细布置 今天两题都挺有难度&#xff0c;建议大家思考一下没思路&#xff0c;直接看题解&#xff0c;第一次做&#xff0c;硬想很难想出来。343. 整数…...

MySQL数据库中基本数据管理操作

使用SQL语句实现基本数据管理操作——即DML语句 1.添加数据 insert into 表名&#xff08;字段名称&#xff0c;字段名称&#xff0c;字段名称&#xff09;values&#xff08;数据&#xff0c;数据&#xff0c;数据&#xff09; 在MySQL数据库中&#xff0c;除了数字&#x…...

记录一下Hql遇到的零碎问题

建表相关 -- 地区维度表 drop table dim_province_full; create table dim_province_full( id string comment 编号, name string comment 省份名称, region_id string comment 大区id, area_code string comment 行政区位码, iso_code string comment 国际编码, iso_3166_2 s…...

Flutter 中的 TextField 小部件:全面指南

Flutter 中的 TextField 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;TextField 是一个允许用户输入文本的小部件。它非常灵活&#xff0c;支持多种文本输入场景&#xff0c;如单行文本、多行文本、密码输入、数值输入等。TextField 还提供了丰富的定制选项&#xf…...

GPT-4o:全面深入了解 OpenAI 的 GPT-4o

GPT-4o&#xff1a;全面深入了解 OpenAI 的 GPT-4o 关于 GPT-4o 的所有信息ChatGPT 增强的用户体验改进的多语言和音频功能GPT-4o 优于 Whisper-v3M3Exam 基准测试中的表现 GPT-4o 的起源追踪语言模型的演变GPT 谱系&#xff1a;人工智能语言的开拓者多模式飞跃&#xff1a;超越…...

2024中国应急(消防)品牌巡展西安站成功召开!惊喜不断

消防品牌巡展西安站 5月10日&#xff0c;由中国安全产业协会指导&#xff0c;中国安全产业协会应急创新分会、应急救援产业网联合主办&#xff0c;陕西消防协会协办的“一切为了安全”2024年中国应急(消防)品牌巡展-西安站成功举办。该巡展旨在展示中国应急&#xff08;消防&am…...

信创电脑|暴雨新增兆芯KX-7000处理器版本

IT世界 5 月 15 日消息&#xff0c;暴雨公司信创家族新上架了一款搭载兆芯KX-7000系列处理器、摩尔线程8GB 显卡、16G DDR5 内存以及 512G SSD 的新配置台式电脑主机。 兆芯 KX-7000 处理器采用开先的 8 核 Chiplet互联架构&#xff0c;最高频率3.7 GHz&#xff0c;拥有 32MB 的…...

面向对象 07:抽象类相关知识,抽象类的基本概念,使用方式,以及一些注意事项

一、前言 记录时间 [2024-05-15] 系列文章简摘&#xff1a; 面向对象 03&#xff1a;类与对象的创建、初始化和使用&#xff0c;通过 new 关键字调用构造方法&#xff0c;以及创建对象过程的内存分析 面向对象 04&#xff1a;三大特性之——封装&#xff0c;封装的含义和作用&a…...

Rust中的链式调用方法

在Rust编程语言中&#xff0c;链式调用是一种流行的编程模式&#xff0c;它允许开发者以流畅、连续的方式调用多个方法。这种风格不仅提高了代码的可读性&#xff0c;而且使得复杂的操作可以串联在一起&#xff0c;形成一个清晰、简洁的语句。在Rust中&#xff0c;链式调用主要…...

xCode升级后: Library ‘iconv2.4.0’ not found

报错信息&#xff1a; targets 选中 xxxNotification: Build Phases ——> Link Binary With Libraries 中&#xff0c;移除 libiconv.2.4.0.tbd libiconv.2.4.0.dylib 这两个库&#xff08;只有一个的移除一个就好&#xff09;。 然后重新添加 libiconv.tbd 修改完…...

SQL语言:完整性约束

完整性约束 数据完整性是指存储在数据库中的数据要能正确反映实际情况&#xff0c;规定输入的数据不能是无效值、错误值 或者乱码等。 一、非空约束&#xff1a; 非空约束关键字&#xff1a; not null 1、非空约束的创建 create table teacher( t_id int not null, -- 为教…...

UBUNTU下CMAKE指定执行文件运行时查找库的路径

在Ubuntu下&#xff0c;使用CMake时&#xff0c;如果需要指定执行文件运行时库的搜索路径&#xff0c;可以在CMakeLists.txt文件中通过set_target_properties命令来设置。 以下是一个示例&#xff0c;假设你的目标是一个名为my_application的可执行文件&#xff0c;你想要添加…...

WHAT - CSS Animationtion 动画系列(四)- 移动端全屏动画

目录 一、背景1.1 GIF & Video1.2 存在的问题 二、技术方案2.1 使用CSS动画和JavaScript2.2 使用JavaScript库2.3 使用序列帧1. css animation 帧动画2. JavaScript requestAnimationFrame 帧动画 2.4 使用Canvas1. html 和 canvas 中的 video2. 基于Canvas的动画库 今天我…...

springboot004网页时装购物系统

springboot004网页时装购物系统 亲测完美运行带论文&#xff1a;获取源码&#xff0c;私信评论或者v:niliuapp 运行视频 包含的文件列表&#xff08;含论文&#xff09; 数据库脚本&#xff1a;db.sql其他文件&#xff1a;ppt.pptx论文/文档&#xff1a;开题报告.docx论文&…...

海外住宅IP介绍

住宅IP&#xff0c;通俗的来讲就是分配给家庭的IP地址&#xff0c;ISP默认分配用户为家庭用户&#xff0c;其真实性与安全性都有一定保障。海外住宅IP是指由海外互联网服务提供商分配给家庭用户的IP地址&#xff0c;IP地址通常是静态的&#xff0c;稳定的&#xff0c;可以为用户…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

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

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

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...