北京网站制作设计与开发服务,cnnic网站,3d效果图什么网站做的好,虚拟主机可以做视频视频网站吗面向对象编程 面向对象编程Object-Oriented Programming#xff0c;OOP#xff09; 作为一种新方法#xff0c;其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征#xff0…面向对象编程 面向对象编程Object-Oriented ProgrammingOOP 作为一种新方法其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征只能对事物特征和变化规律的一种抽象且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。 一、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 封装
分装主要包含两层意思
将数据和操作捆绑在一起创造出一个新的类型的过程。将接口与实现分离的过程。
回顾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应用层业务主要分连接服务器、发送数据、接收应答、断开连接四部分,分别对应open、write、read、close四个操作。 若使用乐鑫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()。 增加了代码的灵活性和可扩展性也实现了代码的应用与驱动分层朝着“高内聚、低耦合”的方向前进。