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

news2024/11/24 18:52:46

文章目录

  • 简述OOPC
  • 开发环境
  • 知识讲解
  • 函数示例
    • 类的实现示例
    • 接口实现示例

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


简述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);

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

#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:

// 类
CLASS (A)
{
	···// 属性及方法
};

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

// 接口
INTERFACE (base)
{
	···// 接口的属性及方法
};

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

#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函数分配内存空间给所声明的对象
  使用示例:

在头文件中使用

	// 类的声明
	class (A)
	{
		void (*fun) (void);
	}
	// 外部声明
	extern A* A_new();

在.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文件

#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文件

#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文件

#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文件

#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文件

#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文件

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



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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/385531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习C++这几个网站足矣

文章目录cppreferencecplusplusquick-bench[C 之父的网站](https://www.stroustrup.com/bs_faq.html)C提案[Cpp Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)[C Super-FAQ](https://isocpp.org/faq)[learn c](https://www.learncpp.com/)[A…

从上海分时电价机制调整看转供电用户电能计费

安科瑞 耿敏花2022年12月16日&#xff0c;上海市发改委发布《关于进一步完善我市分时电价机制有关事项的通知》(沪发改价管〔2022〕50号)。通知明确上海分时电价机制&#xff0c;一般工商业及其他两部制、大工业两部制用电夏季&#xff08;7、8、9月&#xff09;和冬季&#xf…

Codeforces Round 855 (Div. 3)(A~F)

A. Is It a Cat?定义满足条件的字符串为&#xff1a;其中仅可能含有meow四种字母的大小写&#xff0c;而且相同种类的字母必须挨在一起&#xff0c;四种字母的顺序必须按照meow排列。给出一个字母串&#xff0c;求是否满足条件。思路&#xff1a;感觉是个很麻烦的模拟。首先把…

这6个高清图片素材库,马住,马住~

网上找的图片素材清晰度不够&#xff0c;版权不明确怎么办。看看这几个可商用图片素材网站&#xff0c;解决你的所有图片需求&#xff0c;高清无水印&#xff0c;赶紧马住&#xff01; 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库 ​ 网站素材…

Vector - CAPL - 简介及数据结构

对于想进入车载行业或者已经在车载行业工作的朋友对于CAPL这个词都会相当的熟悉&#xff0c;都知道他是做车载网络测试脚本的语言&#xff0c;并且跟C有点类似&#xff0c;但是它到底是什么呢&#xff1f;CAPL全称&#xff08;Communication Access Programming Language&#…

Qt 崩溃 corrupted double-linked list Aborted

文章目录摘要1 使用全局静态变量2 不取第一个和最后一个数3 将数据计算放到同一线程计算4 替换槽函数5 修改传值为const6 神奇的环境因素7 更神奇的板子差异8 另一个细节Aborted最后关键字&#xff1a; Qt、 Aborted、 corrupted、 double、 linked 摘要 额&#xff0c;结论&…

【上位机入门常见问题】SQLServer2019 安装指导

SQLServer2019 安装指导 这里要说一下SQLServer的版本问题&#xff0c;首先说纵向的高低版本&#xff0c;如果大家跟我学习&#xff0c;我教给大家的是T-SQL编程的方法&#xff0c;而不是直接操作菜单的方法&#xff0c;所以&#xff0c;我们学习中只要使用SQLServer2012或以上…

嵌入式学习笔记——STM32单片机开发前的准备

STM32单片机开发前的准备1.集成开发环境的选取STM32 CubeIDEKEIL_MDK2.KEIL_MDK环境搭建安装包获取及安装芯片包下载及安装工程建立(STM32F407VET6为例)1.新建工程文件夹2.新建工程3.安装ST-LINK以及CH340的驱动4.设置KEIL&#xff0c;并烧录本文重点1.集成开发环境的选取 前面…

深入分析Vert.x里Future的compose() 和 map()

Vert.x 是一个异步框架。因此&#xff0c;它需要一种方法来表示可能尚未准备好但将来可用的值&#xff0c;也称为延迟值(deferred values)。您可能熟悉不同名称的延迟值&#xff1a;Promise, Future, Deferred, Mono, Uni 都是延迟值设计模式的实现。 Vert.x 有自己的延迟值实…

IP 地址类型有哪些?

IP 地址有不同的类别&#xff0c;每个类别内有不同的类型。消费者 IP 地址具有互联网服务计划的每个个人或企业都将拥有两种类型的 IP 地址&#xff1a;专用 IP 地址和公共 IP 地址。术语“公共”和“专用”与网络位置有关 - 即&#xff0c;在网络内部使用专用 IP 地址&#xf…

【C++】30h速成C++从入门到精通(内存管理、函数/类模板)

C内存分布我们先来看一下下面的一段代码相关问题int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (int*)mal…

离线数据仓库项目搭建——准备篇

文章目录&#xff08;一&#xff09;什么是数据仓库&#xff08;二&#xff09;数据仓库基础知识&#xff08;三&#xff09;数据仓库建模方式&#xff08;1&#xff09;星行模型&#xff08;2&#xff09;雪花模型&#xff08;3&#xff09;星型模型 VS 雪花模型&#xff08;四…

【iobit 软件】家族系列 - 正版激活码

装机必备iobit系列软件 - 激活码获取看最后 第一款、Advanced SystemCare 16 您需要的人工智能驱动的PC优化器&#xff0c;以释放磁盘空间&#xff0c;加速PC并保护在线隐私。 功能特点&#xff1a; 1. 系统清理与优化&#xff1a;通过清除系统垃圾文件、注册表信息、无用文…

智能微型断路器在某银行网点的设计与应用

安科瑞 耿敏花【摘要】&#xff1a;随着人工智能、移动互联等现代信息技术和通信技术在电力行业的应用&#xff0c;实现电力系统各个环节人机交互、万物互联&#xff0c;打造状态全方面感知、信息合理处理、应用便捷灵活的泛在电力物联网已成为必然趋势 。本文主要对智能微型断…

后羿采集器快速入门----一款没有编程经验也能轻松使用的数据采集软件

后羿采集器快速入门 一、前言 不知道大家有没有苦恼于如何快速获取网页上的数据&#xff1f;想要进行大量重复性的操作但又要花费大量时间经历学习爬虫&#xff0c;这对于没啥编程基础的朋友们来说简直太不友好了&#xff01;那么有没有一个软件&#xff0c;能够通过傻白甜式…

【设计模式】代理模式

代理模式 为某个对象提供一种代理&#xff0c;以控制其他对象对这个对象的访问。属于结构型模式。 某些情况下&#xff0c;一个对象A不适合或者不能引用、直接访问某个对象B&#xff0c;而代理对象可以在客户端A和目标对象B之间起到中介作用 代理模式主要有三个重要角色: 抽…

【推拉框-手风琴】vue3实现手风琴效果的组件

简言 在工作时有时会用到竖形手风琴效果的组件。 在此记录下实现代码和实现思路。 手风琴实现 结构搭建 搭建结构主要实现盒子间的排列效果。 用flex布局或者其他布局方式将内容在一行排列把每一项的内容和项头用盒子包裹&#xff0c; 内容就是这一项要展示的内容&#xf…

python16行代码获取原神全角色+全语音

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 本来是不玩原神的&#xff0c;但是实在是经不住双重诱惑呀~ 毕竟谁能拒绝角色风景超级好看又可以爬树、炸鱼、壶里造房子、抓小动物、躲猫猫的游戏捏~ 今天点进官网~角色得配音让我沉陷其中&#xff0c;于是 我决定把他们爬…

数据库可视化开发工具内容介绍

在现代化办公环境中&#xff0c;数据管理的重要性不言而喻。对于企业来说&#xff0c;将企业内部的数据做好规划和管理&#xff0c;可以给企业提升办公协作效率&#xff0c;为企业高层做出正确的经营决策奠定基础。本文主要给大家介绍的是数据化可视化开发工具的内容&#xff0…

狂神Springmvc,404,500错误解决办法(灵)

b站狂神springmvc404&#xff0c;500解决办法 首先校验各个文件是否正确 配置web.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSche…