【UML+OOPC嵌入式C语言开发】使用C语言实现一个面向对象语言才能够实现的类

    • @[toc]

      (前面两部分有点无聊,如果大家没兴趣看可以直接从知识讲解开始看

      简述OOPC

      oopc,是一种轻量级的面向对象的C语言编程框架 , LW_OOPC是Light-Weight Object-Oriented Programming in(with) C的缩写,总共一个.h文件, 20个宏, 约130行代码, 非常的轻量级, 但却很好的支持了很多面向对象的特性 , 比如继承, 多态。 可以优美的实现面向接口编程。 这个框架是由台湾的高焕堂先生以及他的MISOO团队首创。


      开发环境

      • 采用vscode为IDE
      • 使用makefile编写编译规则
      • 使用GCC编译器

      这里vscode的作用主要是编辑,哈哈哈。至于使用makefile编写编译规则,它既可以减少不必要的编译次数(文件数量较少体现不出),也解决了博主在vscode的同一个项目中,无法同时编译多个.c文件,总之,非常好用。😅🤣


      知识讲解

      面向对象语言开发特性:

      • 封装:根据职责将属性和方法封装到一个抽象的类中;
      • 继承:实现代码的重用,相同的代码不需要重复的写;
      • 多态:以封装和继承为前提,不同的子类对象调用相同的方法,产生不同的执行结果;

      函数指针   指针,形象化地来说就是一个指向一个空间的地址,也就是通过这个指针可以访问这个地址存储的内容。   函数指针,是一个函数经过编译后,计算机会给它分配一段存储空间,而函数指针实际上是指向这段存储空间首地址的一个指针。 那么其函数名就表示函数的指针,代表了函数的起始地址。   函数指针格式为 类型名 (*指针变量名) (函数参数列表),这里的类型名也可以理解为函数返回值的类型。   例如:

      • 一个不带参数的函数指针可以表示为:void (*pFun) (void);
      • 一个带1个参数的函数指针可以表示为:void (*pFun) (int);
      • 一个带1个参数并且有返回值的函数指针可以表示为:int (*pFun) (int);

      当需要指向一个函数时,需要定义一个返回值、函数参数个数类型一致的函数,例如:

      c 复制代码
      #include "stdio.h"
      void fun(void)
      {
      	printf("this is fun\n");
      }
      
      int main(void)
      {
      	void (*p) (void);
      	p = fun;
      	(*p)();
      	
      	return 0;
      }

      其运行结果为:

      那么一起来看看oopc是如何是如何进行面向对象开发的吧!🤤🤤🤤

      关键字CLASS   oopc中,一个类实际上是通过一个结构体实现 。伪关键字CLASS实际上是通过define重新声明得到,实际上其定义为#define CLASS(type) typedef struct type type。(将其称为伪关键字是因为:在面向对语言中其确实是一个关键字,如java、python等确实有关键字class,而oopc的CLASS是通过声明得到,并不是C语言实际存在的关键字。)   例如,定义一个类A:

      c 复制代码
      // 类
      CLASS (A)
      {
      	···// 属性及方法
      };

      关键字IMPLEMENTS   implements关键字,在面向对象语言中,是继承一个接口 比不可少的关键字(这里指java语言)。其实在基于oopc的C语言开发中,也是类似的。   在oopc中,关键字IMPLEMENTS本质也是一个结构体 ,只不过就是将一个结构体变量名重新声明成IMPLEMENTS了,其声明为#define IMPLEMENTS(type) struct type type。(IMPLEMENTS也是一个伪关键字)   明白了类的实现,接口的实现也就简单了,因为两者的本质都是结构体嘛。其实现为:

      c 复制代码
      // 接口
      INTERFACE (base)
      {
      	···// 接口的属性及方法
      };

      构造器CTOR   在oopc中,构造器CTOR是一个非常重要的玩意。   在oopc程序中,设计类是一件重要的工作,其目的是借之产生对象。"构造器"(Constructor)函数,可称之为"对象之母",它能够依照类的定义产生对象。   构造器CTOR在lw_oopc.h文件中的声明为:

      c 复制代码
      #define CTOR(type)                                      \
          type* type##_new() {                                \
          struct type *cthis;                                 \
          cthis = (struct type*)malloc(sizeof(struct type));  \
          if(!cthis)                                          \
          {                                                   \
              return 0;                                       \
          }                                                   \
          type##_ctor(cthis);                                 \
          return cthis;                                       \
      }

      不难看出:CTOR构造器的主要功能为,使用malloc函数分配内存空间给所声明的对象。   使用示例:

      在头文件中使用

      c 复制代码
      	// 类的声明
      	class (A)
      	{
      		void (*fun) (void);
      	}
      	// 外部声明
      	extern A* A_new();

      在.c文件中使用

      c 复制代码
      	// 类的方法
      	static void testFun(void)
      	{
      		printf("this is a fun");
      	}
      	// 使用构造器构造类
      	CTOR (A)
          	FUNCTION_SETTING(fun,testFun);
          END_CTOR	

      在这里需要注意:外部声明函数**extern A* A_new();**声明时一定要使用类的名字,否则会出现报错。(这个声明可加可不加,网上也有很多帖子是使用ANew()来声明一个类的,可能是其修改了lw_oopc.h文件中的声明吧。)


      函数示例

      类的实现示例

      main.c文件

      c 复制代码
      #include <stdio.h>
      #include "light.h"
      #include "lw_oopc.h"
      void main(void)
      {
          printf("class light test\n");
          Light*n = (Light*)Light_new();
          n->init(n);
          printf("light state:%d\n",n->getState(n));
          n->setState(n,1);
          printf("new light state:%d\n",n->getState(n));
      }

      light.c文件

      c 复制代码
      #include "light.h"
      #include "stdio.h"
      #include "lw_oopc.h"
      
      // 灯类的初始化
      static void lightInit(void *light)
      {
          Light*pthis = (Light*)light;
          pthis->state = 0;
      }
      
      // 获取灯的状态
      static int getLightState(void *light)
      {
          Light*pthis = (Light*)light;
          return pthis->state;
      }
      
      // 设置灯的状态
      static void setLightState(void *light,int newState)
      {
          Light*pthis = (Light*)light;
          pthis->state = newState;
      }
      
      // 构造器  分配空间给类
      CTOR (Light)
          FUNCTION_SETTING(init,lightInit);
          FUNCTION_SETTING(getState,getLightState);
          FUNCTION_SETTING(setState,setLightState);
      END_CTOR

      light.h文件

      c 复制代码
      #ifndef  _LIGHT_H
      #define  _LIGHT_H
      
      #include "lw_oopc.h"
      
      CLASS (Light)
      {
          int state;
          void (*init) (void*);
          int (*getState) (void*);
          void (*setState) (void*,int newState);
      };
      
      // 相当于重新new一个灯类
      extern Light* Light_new();
      
      #endif // _DATA_H

      vscode运行结果

      接口实现示例

      main.c文件

      c 复制代码
      #include <stdio.h>
      #include "lw_oopc.h"
      #include "myInterface.h"
      
      // 接口测试
      void main(void)
      {
          // 圆类的实现
          circle*c = (circle*)circle_new();
          c->baseShape.init(c,"circle");
          c->baseShape.draw(c);
          c->vMove(c);
      
          // 正方形类的实现
          square* s = square_new();
          s->baseShape.init(s,"square1");
          s->baseShape.draw(s);
          s->vMove(s);
      }

      myInterface.h文件

      c 复制代码
      #ifndef _MYINTERFACE_H
      #define _MYINTERFACE_H
      
      #include "lw_oopc.h"
      
      // 接口
      INTERFACE (baseShape)
      {
          char name[10];
          void (*init) (void*,char*);
          void (*draw) (void*);
      };
      
      // 圆类
      CLASS (circle)
      {
          IMPLEMENTS (baseShape);
          void (*vMove) (void*);
      };
      extern circle* circle_new();
      
      // 正方形类
      CLASS (square)
      {
          IMPLEMENTS (baseShape);
          void (*vMove) (void*);
      };
      extern square* square_new();
      
      #endif //_MYINTERFACE_H

      myInterface.c文件

      c 复制代码
      #include "myInterface.h"
      #include "string.h"
      #include "stdio.h" 
      
      /********************圆类的实现*******************/
      
      void cinit(void*p,char*name)
      {
          circle*pthis = (circle*)p;
          strcpy(pthis->baseShape.name,name);
      }
      
      void cdraw(void*p)
      {
          circle*pthis = (circle*)p;
          printf("%s drawing\n",pthis->baseShape.name);
      }
      
      void cmove(void *p)
      {
          circle*pthis = (circle*)p;
          printf("%s moving\n",pthis->baseShape.name);
      }
      
      
      CTOR (circle)
          FUNCTION_SETTING(vMove,cmove);
          FUNCTION_SETTING(baseShape.init,cinit);
          FUNCTION_SETTING(baseShape.draw,cdraw);
      END_CTOR
      
      
      /********************正方形类的实现*******************/
      void sinit(void*p,char*name)
      {
          square*pthis = (square*)p;
          strcpy(pthis->baseShape.name,name);
      }
      
      void sdraw(void*p)
      {
          square*pthis = (square*)p;
          printf("%s drawing\n",pthis->baseShape.name);
      }
      
      void smove(void *p)
      {
          square*pthis = (square*)p;
          printf("%s moving\n",pthis->baseShape.name);
      }
      
      
      CTOR (square)
          FUNCTION_SETTING(vMove,smove);
          FUNCTION_SETTING(baseShape.init,sinit);
          FUNCTION_SETTING(baseShape.draw,sdraw);
      END_CTOR

      结果


      lw_oopc相关的文件大家可以去gitee或者是github上面找找,上面有很多示例,博主还没完全码明白。oopc相关文件的示例仓库😅😅😅



      小编会持续更新的哟!欢迎大家点赞+收藏+关注!!!🤤🤤🤤

相关推荐
潍坊老登2 天前
90%的软件项目卡在第一步:需求“想得美、写不清”
编程语言
iiiiyu2 天前
面向对象高级接口的综合案例
java·开发语言·数据结构·编程语言
Rust研习社2 天前
Rust 是如何判断对象是否相等的?一起来聊一聊 PartialEq 与 Eq
后端·rust·编程语言
7年前端辞职转AI3 天前
Python 错误和异常处理
python·编程语言
7年前端辞职转AI3 天前
Python 面向对象编程
python·编程语言
7年前端辞职转AI4 天前
Python 文件操作
python·编程语言
7年前端辞职转AI4 天前
Python 容器数据类型
python·编程语言
7年前端辞职转AI4 天前
Python 流程控制语句
python·编程语言
7年前端辞职转AI4 天前
Python 运算符
python·编程语言