在 C 语言里,可以用 struct + 函数指针 来模拟"类":结构体里既放数据成员 ,也放成员函数指针。这就是 C 语言里常见的"用 struct 实现类定义"的写法。
下面把串口接收封装成一个"类"。
一、类定义(头文件风格)
cpp
#ifndef __UART_RX_H
#define __UART_RX_H
#define TRUE 1
#define FALSE 0
#define RX_BUFFER_SIZE 256
/* 前向声明:类的类型名 */
typedef struct UartRx UartRx;
/* 类结构体:数据成员 + 成员函数指针 */
struct UartRx
{
/* ---------- 数据成员 ---------- */
char buf[RX_BUFFER_SIZE]; /* 接收缓冲区 */
unsigned int index; /* 写入位置 */
unsigned char complete; /* 接收完成标志 */
unsigned char overflow; /* 溢出标志 */
/* ---------- 成员函数(函数指针) ---------- */
void (*init) (UartRx *self); /* 构造/初始化 */
void (*handler)(UartRx *self, char data); /* 接收一个字节 */
char *(*getString)(UartRx *self); /* 取字符串 */
void (*reset) (UartRx *self); /* 复位 */
};
/* 构造函数:返回一个初始化好的对象 */
void UartRx_Create(UartRx *self);
#endif
二、类的实现(.c 文件风格)
cpp
#include <string.h>
#include "uart_rx.h"
/* ---------- 成员函数实现 ---------- */
static void UartRx_init(UartRx *self)
{
memset(self->buf, 0, sizeof(self->buf));
self->index = 0;
self->complete = FALSE;
self->overflow = FALSE;
}
static void UartRx_handler(UartRx *self, char data)
{
if (self->complete) /* 上一帧未处理 */
{
return;
}
if (data == '\n') /* 换行 → 一帧结束 */
{
self->buf[self->index] = '\0';
self->complete = TRUE;
return;
}
if (data == '\r') /* 忽略回车 */
{
return;
}
if (self->index < (RX_BUFFER_SIZE - 1))
{
self->buf[self->index++] = data;
}
else
{
self->overflow = TRUE;
self->index = 0;
}
}
static char *UartRx_getString(UartRx *self)
{
return self->buf;
}
static void UartRx_reset(UartRx *self)
{
self->index = 0;
self->complete = FALSE;
self->overflow = FALSE;
memset(self->buf, 0, sizeof(self->buf));
}
/* ---------- 构造函数:绑定成员函数 ---------- */
void UartRx_Create(UartRx *self)
{
self->init = UartRx_init;
self->handler = UartRx_handler;
self->getString = UartRx_getString;
self->reset = UartRx_reset;
self->init(self); /* 调用初始化 */
}
三、使用示例(像用对象一样)
cpp
#include <stdio.h>
#include "uart_rx.h"
int main(void)
{
UartRx uart1; /* 相当于"声明一个对象" */
UartRx_Create(&uart1); /* 相当于"构造对象" */
const char *test = "Hello\r\n";
const char *p = test;
while (*p)
{
uart1.handler(&uart1, *p++); /* 调用"成员函数",显式传 self */
if (uart1.complete == TRUE)
{
printf("收到一帧: %s\n", uart1.getString(&uart1));
uart1.reset(&uart1);
}
}
return 0;
}
