Java教程

面向对象编程基础

本文主要是介绍面向对象编程基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

RTOS嵌入式系统框架进阶

第一章 嵌入式常用裸机编程框架
第二章 面向对象编程基础


文章目录

    • **RTOS嵌入式系统框架进阶**
  • 前言
    • 1、未使用面向对象编程的程序
      • 1.1、库函数编程
      • 1.2、使用子函数
    • 2、使用面向对象编程的程序
      • 2.1、 函数指针
      • 2.2、 结构体
  • 总结


前言

学习韦东山老师的七天物联网实战及直播课相关内容,以其课程笔记为骨,记录一下学习的过程,可能会加入一些自己的感想。
最后欢迎点赞、收藏与评论交流!


面向对象的总体思想来源《代码大全》的第5章,他把程序设计分为这以下几个层次:

  • 第1层:软件系统,就是整个系统、整个程序
  • 第2层:分解为子系统或包。比如我们可以拆分为:输入子系统、显示子系统、业务系统
  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
  • 第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

为了方便阅读,本文从底层开始介绍代码,由底向上进行介绍,这样更方便阅读。本文主要介绍第4层与第3层的内容。


1、未使用面向对象编程的程序

1.1、库函数编程

以按键为例进行说明:

硬件原理图

以下代码实现以下功能,key值代表是否按下按键PF6。如果按下按键,就点亮LED灯;若没有按下按键,则关闭LED。

void main(void)
{
    GPIO_PinState key;
    while (1)
    {
        key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
        if (key == GPIO_PIN_RESET)
            HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_RESET);
        else
            HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_SET);
    }
}

但这样写代码有明显的缺陷:

  • 需要结合原理图、需要有硬件知识
  • 很难进行今后的代码维护和扩展

1.2、使用子函数

为了使自己的代码尽量远离硬件知识,我们在程序中加入大量的子函数。这样预留的API可以大大提高程序的可阅读性。方便以后自己代码的扩展,也方便与上层的算法人员进行代码的交流。

// main.c
void main(void)
{
    int key;
    while (1)
    {
        key = read_key();
        if (key == UP)
            led_on();
        else
            led_off();
    }
}

// key.c
int read_key(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;
}

// led.c
void led_on(void)
{
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_RESET);
}

void led_off(void)
{
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_SET);
}

但此时我们仅完成了

第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

当程序中包含特别多的子函数时,有串口的,LED灯的,按键的,CAN口、SPI等等,这时候大量的子函数放到一起就会很头痛,因此我们想要将一些功能相似的函数耦合起来,这样更上一层楼到进到第三层:

  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。

2、使用面向对象编程的程序

面向对象编程的基础是结构体与函数指针,因此在本节中我们先对函数指针和结构体进行介绍。

2.1、 函数指针

指针是C语言的灵魂,是必须掌握的内容,在此我先进行简单的介绍,如果后期看的人多并且点赞多的话,我会写专门的文章进行说明。

指针的基本概念是指向地址的变量,而指针也有相应的类型:例如int *P表示的是指针,并且大小为4个字节的内存的内容。其他数据类型有类似的效果。

而函数指针代表的是指向函数入口的指针变量,通过调用指针就可以找到函数入口,从而实现函数的调用。

假如有两个版本的按键读取函数,通过函数指针来确定哪一个使用哪一个版本的代码,代码如下(示例):

int (*read_key)(void);

// 返回值: 0表示被按下, 1表示被松开
int read_key_ver1(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_5);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;            
}

// 返回值: 0表示被按下, 1表示被松开
int read_key_ver2(void)
{
    GPIO_PinState key;
    key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
    if (key == GPIO_PIN_RESET)
        return 0;
    else
        return 1;            
}

void key_init()
{
    int ver = read_hardware_ver();// 读取硬件版本,版本1读PF5,版本2读PF6
    if (ver == 1)
        read_key = read_key_ver1;
    else
        read_key = read_key_ver2;
}

// main.c
void main(void)
{
    int key;
    
    key_init();
    
    while (1)
    {
        key = read_key();
        if (key == UP)
            led_on();
        else
            led_off();
    }
}

2.2、 结构体

面向对象的初衷是为了解决一类问题,因此要解决的是一类问题,即:
- 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
在本文中就是要表达所有的按键处理函数。

本例中代表一个系统共有两个按键,通过结构体的表述代码如下所述(示例):

// key.c
// 返回值: 0表示被按下, 1表示被松开
int read_key(int which)
{
    GPIO_PinState key;
    switch (which)
    {
        case 0:
			key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_6);
            if (key == GPIO_PIN_RESET)
                return 0;
            else
                return 1;
            break;
            
        case 1:
			key = HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_7);
            if (key == GPIO_PIN_RESET)
                return 1;
            else
                return 0;
            break;
            
    }
}

该方法在小的系统代码中使用较多,但是不太容易进行扩展,如果想要加K3的话仍然需要再写一个case分支。

改进方法是通过结构体进行函数的编写,在结构体中包含指针函数的成员,这样关于按键的操作基本都被一个结构体所包含了。具体过程如下所述:

定义一个结构体变量代码示例如下:

typedef struct key {
	char *name;
    void (*init)(struct key *k);
    int (*read)(struct key *k);
}key, *p_key;

每个按键都实现一个key结构体:

// key1.c
key k1 = {"k1", NULL, read_key1};

// key2.c
key k2 = {"k2", NULL, read_key2};

// key_net.c
key k_net = {"net", NULL, read_key_net};

总结

本文主要讲述了子函数、指针函数和结构体体的内容,主要完成的是代码第3和第4层的内容;

  • 第3层:分解为类。在C语言里没有类,可以使用结构体来描述子系统。
  • 第4层:分解成子程序:实现那些结构体(结构体中有函数指针)。

为接下来的代码分层打下基础,在下一篇文章中我们将主要介绍第2和1层的内容。如有不清楚的,欢迎提问或指出错误。

这篇关于面向对象编程基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!