news 2026/4/29 19:19:03

08_C 语言进阶之面向对象编程:模块化及抽象思维 —— 用过程式语言构建面向对象的世界

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
08_C 语言进阶之面向对象编程:模块化及抽象思维 —— 用过程式语言构建面向对象的世界

C 语言进阶之面向对象编程:模块化及抽象思维 —— 用过程式语言构建面向对象的世界

一、C 语言真的不能搞面向对象吗?

“C 语言是过程式语言,只能写面条代码?”

“项目变大后,C 代码耦合度高、维护难,难道只能转 C++?”

“想实现代码复用、数据封装,C 语言有没有优雅的方式?”

“模块化开发时,如何避免全局变量满天飞、函数命名冲突?”

提到面向对象编程(OOP),人们往往首先想到 C++、Java、Python 等语言,而将 C 语言归为 “面向过程” 的 “原生派”,认为其无法实现面向对象的核心特性。但事实上,面向对象是一种编程思想,而非某类语言的专属特性。C 语言虽然没有提供类、继承、多态等语法糖,但可以通过模块化设计、函数指针、结构体、抽象接口等语法特性,完美模拟面向对象的三大核心特性:封装、继承、多态,更能在这个过程中,深度锤炼开发者的抽象思维

在嵌入式开发、操作系统内核、大型工业软件等场景中,C 语言的面向对象式编程(常被称为 “C++ 之前的面向对象”)早已被广泛应用 ——Linux 内核中的file_operations结构体、STM32 HAL 库中的外设驱动模型,本质上都是面向对象思想的 C 语言实现。

本文将从 “模块化设计” 到 “面向对象核心特性模拟”,再到 “抽象思维培养”,一步步带你掌握 C 语言中的面向对象编程技巧,让你的 C 代码也能具备高内聚、低耦合、可扩展、可复用的面向对象特质。

二、基础:模块化编程 —— 面向对象的前置条件

面向对象的核心是 “对象”,而对象的构建首先依赖于模块化。模块化是将复杂程序拆分为多个独立的、功能单一的模块(文件),每个模块负责一个特定的功能域,这是降低代码耦合度、提升可维护性的基础,也是 C 语言迈向面向对象的第一步。

(一)C 语言模块化的核心准则:高内聚、低耦合

  1. 高内聚:一个模块内的所有代码都围绕一个核心功能展开,不包含无关的逻辑。例如,一个uart模块只负责串口的初始化、发送、接收,不掺杂 LED 控制的代码。

  2. 低耦合:模块之间通过少量的、明确的接口通信,不直接访问彼此的内部数据。例如,uart模块只对外暴露uart_init()uart_send()等函数,内部的缓冲区、状态变量对外部不可见。

(二)C 语言模块化的实现方式:.h 头文件 + .c 源文件

这是 C 语言模块化的标准范式,通过头文件暴露接口,源文件实现细节,具体分为三步:

1. 定义模块的头文件(*.h):暴露接口,隐藏实现

头文件中只存放函数声明、宏定义、结构体前向声明、枚举类型,不存放函数实现、全局变量定义(除非是对外暴露的常量)。

// uart.h:串口模块的头文件(接口层)#ifndef__UART_H__// 防止头文件重复包含(必加)#define__UART_H__#include<stdint.h>// 枚举:串口波特率(对外暴露的常量)typedefenum{UART_BAUD_9600=9600,UART_BAUD_115200=115200,UART_BAUD_460800=460800}UartBaud;// 结构体前向声明:隐藏内部实现(关键)typedefstructUartHandleUartHandle;// 接口函数声明:模块对外提供的功能// 创建串口句柄(类似面向对象的构造函数)UartHandle*uart_create(uint8_tuart_num,UartBaud baud);// 串口发送数据voiduart_send(UartHandle*handle,constuint8_t*data,uint32_tlen);// 串口接收数据uint32_tuart_recv(UartHandle*handle,uint8_t*buf,uint32_tbuf_len);// 销毁串口句柄(类似面向对象的析构函数)voiduart_destroy(UartHandle*handle);#endif// __UART_H__

关键技巧

  • 使用typedef struct UartHandle UartHandle;进行结构体前向声明,而不暴露结构体的内部成员,实现数据隐藏(封装的基础)。

  • 头文件保护宏(#ifndef __UART_H__)必须添加,避免重复包含导致的编译错误。

  • 接口函数以模块名开头(如uart_*),避免命名冲突。

2. 实现模块的源文件(*.c):封装细节,实现接口

源文件中存放结构体的具体定义、函数实现、静态全局变量(仅在本模块内可见)。

// uart.c:串口模块的源文件(实现层)#include"uart.h"#include<stdlib.h>#include<string.h>// 引入硬件相关头文件(如STM32)#include"stm32f10x_usart.h"// 结构体的具体定义:仅在本模块内可见(封装)structUartHandle{uint8_tuart_num;// 串口号UartBaud baud;// 波特率uint8_trx_buf[1024];// 接收缓冲区uint32_trx_len;// 接收数据长度USART_TypeDef*uart_periph;// 硬件外设指针};// 静态函数:仅在本模块内调用(私有方法)staticvoiduart_hw_init(UartHandle*handle){// 硬件初始化逻辑(如STM32的USART配置)if(handle->uart_num==1){handle->uart_periph=USART1;// ... 引脚、时钟、波特率配置}elseif(handle->uart_num==2){handle->uart_periph=USART2;// ... 配置}}// 接口函数实现:创建串口句柄UartHandle*uart_create(uint8_tuart_num,UartBaud baud){// 动态分配内存(类似对象的实例化)UartHandle*handle=(UartHandle*)malloc(sizeof(UartHandle));if(handle==NULL){returnNULL;}// 初始化成员变量memset(handle,0,sizeof(UartHandle));handle->uart_num=uart_num;handle->baud=baud;// 调用私有方法初始化硬件uart_hw_init(handle);returnhandle;}// 接口函数实现:串口发送voiduart_send(UartHandle*handle,constuint8_t*data,uint32_tlen){if(handle==NULL||data==NULL||len==0){return;}// 发送逻辑:通过handle访问硬件外设for(uint32_t
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 0:00:28

Day 39 MLP神经网络的训练

浙大疏锦行 神经网络是一种模拟人脑神经元连接结构的分层模型&#xff0c;核心通过“输入层→隐藏层→输出层”的架构实现端到端学习&#xff0c;无需手动设计特征&#xff0c;能自动提取数据中的高阶非线性关系&#xff08;如心脏病风险与年龄、血压的复杂关联&#xff09;。…

作者头像 李华
网站建设 2026/4/25 19:20:19

浏览器原理

浏览器原理 一、 宏观视角&#xff1a;Chrome 多进程架构 现在的浏览器更像是一个分布式操作系统&#xff0c;而非简单的应用程序。 1. 四大核心进程 Browser Process (主进程)&#xff1a; 职责&#xff1a;负责 UI&#xff08;地址栏、书签&#xff09;、协调子进程、管理存储…

作者头像 李华
网站建设 2026/4/18 5:21:19

XXL-TOOL v2.4.0 发布 | 布隆过滤器、Excel流式读写、高性能BeanCopy

Release Notes 1、【新增】BloomFilter&#xff08;布隆过滤器&#xff09;&#xff1a;一种基于多哈希函数和位数组的概率型数据结构&#xff0c;具有高效空间利用与快速查询特性&#xff1b;2、【新增】Trie&#xff08;前缀数&#xff09;&#xff1a;一种哈希树的变种&…

作者头像 李华
网站建设 2026/4/26 6:00:01

管理软件包

一.rpm管理软件包1.安装软件-i安装指定一个或多个软件包-v显示安装过程-h以#号显示安装进度2.查询软件-q查询软件包信息-a查询已经安装的软件包-c显示软件包的配置文件列表-d显示软件包的文本文件列表-p查询软件包文件&#xff0c;通常和其他选项组合使用-g查询所属组的软件包-…

作者头像 李华
网站建设 2026/4/26 16:54:42

DAY24 奇异值SVD分解

一、SVD的实际价值 1. 计算效率提升 特征从n维降至k维&#xff08;k<n&#xff09; 减少模型参数数量 加快训练和预测速度 2. 模型泛化能力 去除噪声和冗余信息 可能提高模型在测试集上的表现 减少过拟合风险 二、实际书写思路及其代码 针对心脏并数据集我们进行了…

作者头像 李华
网站建设 2026/4/27 23:14:55

GUID为什么不会重复?

GUID为什么不会重复? GUID/UUID &#xff08;全局唯一标识符&#xff09;之所以被认为“几乎不会重复”&#xff0c;是因为其庞大的组合空间和精心设计的生成算法&#xff0c;使得在现实世界中重复的概率低到可以忽略不计。 以下是 GUID 不会重复的核心原因&#xff1a; 1. 庞…

作者头像 李华