【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相关文件的示例仓库😅😅😅



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

相关推荐
咕噜Yuki06093 天前
Java基础篇:学会这些技能,程序员职场竞争力UP UP
java·开发语言·编程语言
codeGoogle3 天前
计算机书籍打包
前端·后端·编程语言
Moonbit4 天前
MoonBit 双周报 Vol.59:新增编译器常量支持,改进未使用警告,支持跨包函数导入...多个关键技术持续优化中!
编程语言
神经星星4 天前
【TVM 教程】外部张量函数
人工智能·开源·编程语言
Moonbit8 天前
MGPIC案例分享|零基础早鸟教程:8小时使用 wasm4 开发井子棋小游戏!
编程语言
邓校长的编程课堂10 天前
少儿编程进入义务教育课程:培养信息科技素养的新政策解读
科技·编程语言·少儿编程·信息学竞赛·科技特长生·义务教育
Moonbit18 天前
MoonBit 双周报 Vol.58:原生后端支持、多行字符串插值、json.inspect 功能等多项关键特性取得显著进展!
编程语言
小尤笔记1 个月前
Python操作系统的6个自动化脚本
数据库·python·自动化·php·编程语言·python入门
神经星星1 个月前
【TVM 教程】使用 Relay Visualizer 可视化 Relay
人工智能·机器学习·编程语言
GoppViper2 个月前
golang学习笔记17——golang使用go-kit框架搭建微服务详解
笔记·后端·学习·微服务·golang·编程语言·go-kit