C语言面向对象的编程思想

面向对象编程

面向对象编程Object-Oriented Programming,OOP)
作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。

一、OOP的优势

(来自chatgpt)

代码组织和可读性提升: 使用类似于对象的结构体和函数指针来组织代码,可以将相关的数据和操作放在一起,使代码更易于理解和维护。

封装和信息隐藏: 通过将数据隐藏在结构体中,只暴露必要的操作接口,实现对实现细节的封装,避免外部直接访问内部数据,增强了代码的安全性。

代码重用和扩展性: 使用类似于继承的技巧,可以创建派生结构体来扩展已有的功能,实现代码的重用和扩展,减少了重复编写代码的工作量。

多态性和灵活性: 通过函数指针的动态绑定,可以在运行时根据对象的类型调用相应的方法,实现多态的效果,增加了代码的灵活性和可扩展性。

更接近硬件: C语言相对较接近底层,通过模拟面向对象的方式,可以在嵌入式系统等场景中实现更高层次的代码组织和抽象。

代码可测试性: 将数据和操作封装在对象中,可以更容易地进行单元测试,通过独立测试对象的方法,减少了测试复杂性。

二、如何实现OOP

尽管C语言时面向过程,但可以通过结构体和函数指针模拟面向对象编程。后面会以rt-thread的设备源码分析OOP的实现。以I/O设备模型为例,其模型如下图所示:
在这里插入图片描述

图一 rt-thread的IO设备

2.1 抽象

对于单片机来说有很多驱动外设,如GPIO、UART、SPI、I2C等,这些外设都可以抽象成一个设备结构体rt_device其定义如下

struct rt_device
{struct rt_object          parent;        /* 内核对象基类 */enum rt_device_class_type type;          /* 设备类型 */rt_uint16_t               flag;          /* 设备参数 */rt_uint16_t               open_flag;     /* 设备打开标志 */rt_uint8_t                ref_count;     /* 设备被引用次数 */rt_uint8_t                device_id;     /* 设备 ID,0 - 255 *//* 数据收发回调函数 */rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);const struct rt_device_ops *ops;    /* 设备操作方法 *//* 设备的私有数据 */void *user_data;
};
typedef struct rt_device *rt_device_t;

我们可以想象一下GPIO、UART、SPI、I2C这些不同的外设是否都具有这些属性和方法。

2.2 封装

分装主要包含两层意思:

  1. 将数据和操作捆绑在一起,创造出一个新的类型的过程。
  2. 将接口与实现分离的过程。

回顾rt_device 结构体,将该对象的属性与该对象具有的方法ops封装在一起,便于代码的维护。外部程序只能通过结构体访问相关数据也增加了代码的安全性。

2.3 继承

rt_device结构体中存在一个基类rt_object也是其父类。也就是说每个rt_device都从rt_object中继承了这些属性。每次使用rt_device声明不同对象时都不需要重复定义rt_object,实现代码的重用和扩展,减少了重复编写代码的工作量。

struct rt_object
{char       name[RT_NAME_MAX];                       /**< name of kernel object */rt_uint8_t type;                                    /**< type of kernel object */rt_uint8_t flag;                                    /**< flag of kernel object */void      *module_id;                               /**< id of application module */rt_list_t  list;                                    /**< list node of kernel object */
};

2.4 多态

rt_device结构体中存在 rt_device_ops *ops 方法。

/*** operations set for device object*/
struct rt_device_ops
{/* common device interface */rt_err_t  (*init)   (rt_device_t dev);rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);rt_err_t  (*close)  (rt_device_t dev);rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
};

通过函数指针的方式实现多态。实际项目中我们会遇到多个模块的适配问题,比如AT的wifi模块,犹豫各个厂商AT指令不兼容,当项目中产生替代料时,使用多态则再合适不过了。
对于client应用层业务主要分:连接服务器发送数据接收应答断开连接四部分,分别对应openwritereadclose四个操作。
若使用乐鑫esp则需要实现esp_connect(),esp_send(),esp_recv(),esp_close()四个功能,
若使用移远模块,则需要实现quectel_connect(),quectel_send(),quectel_recv(),quectel_close()功能。
通过device_init函数使client.ops根据实际模块绑定对应函数即可。APP层操作只会是client.ops->open()client.ops->write(),client.ops->read(),client.ops->close()
增加了代码的灵活性和可扩展性,也实现了代码的应用与驱动分层,朝着“高内聚、低耦合”的方向前进。

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

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

相关文章

MVC OR DDD

MVC OR DDD 说明&#xff1a;这篇是标题党&#xff0c;不包含相关概念说明 前段时间跟随师兄学习了解了DDD领域驱动模型&#xff0c;觉得这个思想更好&#xff0c;进行下面解析和学习方面的思考和实践&#xff0c;觉得很好&#xff0c;耐心读下去。希望对您有所帮助。 首先&am…

基于ADAU1452 DSP ANC和AEC算法的实现

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?加我微信hezkz17, 本群提供音频技术答疑服务,+群附加赠送,DSP音频项目核心开发资料, 1 使用Sigma中的NLMS算法模块 对应C源代码:

JavaSE 集合框架及背后的数据结构

目录 1 介绍2 学习的意义2.1 Java 集合框架的优点及作用2.2 笔试及面试题 3 接口 interfaces3.1 基本关系说明3.2 Collection 常用方法说明3.3 Collection 示例3.4 Map 常用方法说明3.5 Map 示例 4 实现 classes5 Java数据结构知识体系5.1 目标5.2 知识点 1 介绍 集合&#xf…

如何自己实现一个丝滑的流程图绘制工具(七)bpmn-js 批量删除、复制节点

背景 希望实现批量删除和复制节点&#xff0c;因为bpmn-js是canvas画的&#xff0c;所以不能像平时页面上的复制一样直接选择范围&#xff0c;会变成移动画布。 思路是&#xff1a; 绘制一个选择的效果框&#xff0c;这样才可以看出来选的节点有哪些。 上面的选中范围框效果…

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)

温故知新 &#x1f4da;第三章 Kubernetes各组件部署&#x1f4d7;安装kubectl&#xff08;可直接跳转到安装kubeadm章节&#xff0c;直接全部安装了&#xff09;&#x1f4d5;下载kubectl安装包&#x1f4d5;执行kubectl安装&#x1f4d5;验证kubectl &#x1f4d7;安装kubead…

Go死码消除

概念: 死码消除(dead code elimination, DCE) 是一种编译器优化技术, 作用是在编译阶段去掉对程序运行结果没有任何影响的代码 和 逃逸分析[1],内联优化[2]并称为 Go编译器执行的三个重要优化 效果: 对于 const.go代码如下: package mainimport "fmt"func max(a, b i…

wireshark过滤器的使用

目录 wiresharkwireshark的基本使用wireshark过滤器的区别 抓包案例 wireshark wireshark的基本使用 抓包采用 wireshark&#xff0c;提取特征时&#xff0c;要对 session 进行过滤&#xff0c;找到关键的stream&#xff0c;这里总结了 wireshark 过滤的基本语法&#xff0c;…

芯科科技宣布推出下一代暨第三代无线开发平台,打造更智能、更高效的物联网

第三代平台中的人工智能/机器学习引擎可将性能提升100倍以上 Simplicity Studio 6软件开发工具包通过新的开发环境将开发人员带向第三代平台 中国&#xff0c;北京 - 2023年8月22日 – 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&…

java定位问题工具

一、使用 JDK 自带工具查看 JVM 情况 在我的机器上运行 ls 命令&#xff0c;可以看到 JDK 8 提供了非常多的工具或程序&#xff1a; 接下来&#xff0c;我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用&#xff1a; 为了测试这些工具&#x…

从LeakCanary看内存快照解析

在从LeakCanary看内存快照生成一节中&#xff0c;我们已经了解了hprof的生成&#xff0c;并且将生成的hprof文件通过Android Studio进行解析&#xff0c;确实发现了内存泄漏对象MainActivity&#xff0c;但是在实际开发中&#xff0c;要求开发者自己去手动pull hprof文件进行解…

5.基于多能互补的热电联供型微网优化运行

MATLAB代码链接&#xff1a;基于多能互补的热电联供型微网优化运行 MATLAB代码&#xff1a;基于多能互补的热电联供型微网优化运行 关键词&#xff1a;多能互补 综合需求响应 热电联产 微网 优化调度 参考文档&#xff1a;《基于多能互补的热电联供型微网优化运行》基本完全…

链表(详解)

一、链表 1.1、什么是链表 1、链表是物理存储单元上非连续的、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表的指针地址实现&#xff0c;有一系列结点&#xff08;地址&#xff09;组成&#xff0c;结点可动态的生成。 2、结点包括两个部分&#xff1a;&#x…

OLED透明屏显示技术:未来显示科技的领航者

OLED透明屏显示技术是一种创新性的显示技术&#xff0c;它的特殊性质使其成为未来显示科技的领航者。 OLED透明屏具有高对比度、快速响应时间、广视角和低功耗等优势&#xff0c;同时&#xff0c;其透明度、柔性和薄型设计使其成为创新设计的理想选择。 本文将深入探讨OLED透…

NSS [NUSTCTF 2022 新生赛]Ezjava1

NSS [NUSTCTF 2022 新生赛]Ezjava1 题目描述&#xff1a;你能获取flag{1}吗 开题&#xff0c;一眼java web中的index.jsp。 默认index.jsp中的body内容是$END$ 附件jar包导入IDEA&#xff0c;会自动反编译。看看源码。 附件结构大致如此。主要看classes.com.joe1sn中的代码就…

MyBatisx代码生成

MyBatisx代码生成 1.创建数据库表 CREATE TABLE sys_good (good_id int(11) NOT NULL,good_name varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,good_desc varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (good_id) ) ENGINEInnoDB DEFAULT CHA…

【C++设计模式】用动画片《少年骇客》(Ben10)来解释策略模式

2023年8月25日&#xff0c;周五上午 今天上午学习设计模式中的策略模式时&#xff0c;发现这个有点像很多卡通片里面的变身器... 2023年8月26日&#xff0c;周六上午 更新&#xff1a;和简单工厂模式结合 目录 用策略模式写主角的变身器 使用策略模式的好处和简单工厂模式结…

手写实现call() apply() bind()函数,附有详细注释,包含this指向、arguments讲解

手写实现call() apply() bind()函数是很经典的问题&#xff0c;但是能掰扯清楚的文章确实不算多&#xff0c;于是笔者才决定写下本文&#xff0c;希望能给读者带来一些启发&#xff0c;如有错误欢迎指正。 目录 补充知识 函数中的this指向 类数组对象arguments call() 原理…

每日三题 1448统计二叉树中好节点的个数 100相同的树 101对称二叉树

1448 题目 给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,3,null,1,5] 输出&#xff…

弯道超车必做好题集锦三(C语言选择题)

前言&#xff1a; 编程想要学的好&#xff0c;刷题少不了&#xff0c;我们不仅要多刷题&#xff0c;还要刷好题&#xff01;为此我开启了一个弯道超车必做好题锦集的系列&#xff0c;每篇大约10题左右。此为第三篇选择题篇&#xff0c;该系列会不定期更新&#xff0c;后续还会…

MongoDB实验——在Java应用程序中操作 MongoDB 数据

在Java应用程序中操作 MongoDB 数据 1. 启动MongoDB Shell 2. 切换到admin数据库&#xff0c;使用root账户 3.开启Eclipse&#xff0c;创建Java Project项目&#xff0c;命名为MongoJava File --> New --> Java Project 4.在MongoJava项目下新建包&#xff0c;包名为mo…