当前位置: 首页 > 科技观察

真的可以,用C语言实现面向对象编程OOP

时间:2023-03-19 22:39:24 科技观察

解释C语言和OOP的区别我们常说C语言是面向过程的,而C++是面向对象的,但是什么是面向对象什么是加工型呢绒呢?不管怎样,我们最原始的目标是实现我们需要的功能。从这一点来看,他们是殊途同归。过程和对象只是侧重点不同。比如我现在有去北京的打算。OOP语言是直接给你一辆车,然后你自己定好去北京的路线,而C语言则需要你自己制造零件,自己组装汽车。然后自己定好路线,终于到达北京。C语言比较费力,但是程序效率很高。过程和对象?一个对象是由这个对象或多或少的程序组成的,当然,必要的属性是少不了的。过程是对一个或多个对象执行的操作。两者可以相互转化。关键是哪种方法更适合你当前的需求,能让你的软件开发更出色。我个人认为,一般来说,一个更容易扩展和维护的软件,通常都会采用OOP的思想。与其强加一个对象到一个已经存在的过程中,不如加入一个相对不相关的不存在的个体。要简单;面向过程更容易导致维护混乱。比如同样是河流和湖泊,哪个更容易管理和维护?我认为答案是显而易见的。当然,不管怎样,软件本身的设计架构也很重要。C语言的特点,OOPC是一种面向过程的语言,但它仍然可以实现面向对象能做的大部分工作。比如面向对象的三大特点:封装、继承、多态。下面我们来写一个代码示例。封装是因为面向对象就是把数据和方法封装到一个类中。用户不需要关心类是如何实现的。这个想法是在C_OOP中实现的。C中有一个复杂的数据结构,叫做struct。struct是C中的一个结构体,如上所示,如果我们要对鸟bird进行封装,那么bird可能包含名称、颜色、栖息地、体重、属性等信息。我们可以这样封装:structBird{charname[20];//namecharcolor;//colorcharaddr[30];//habitatintweight;//weightintoother;//property};当我们想要像OOP一样创建一个新的对象时,我们可以:structBirdp;我们可以直接给p赋值:p.name="bird";p.color='b';//'b'=black;'g'=greenp。addr='w';p.weight=175;p.other=1;Inheritance在C语言实现继承的常见机制中,大部分都是通过组合结构来实现的。也可以使用struct创建一个Bird结构。同时继承结构体Bird,如下:structfBird{structBirdp;charfly[20];//flyingintscream;//tweeting};为Bird创建一个对象并赋值:structfBirds;s.p.name="bird";s.p.color='b';s.p.other=25;s.p.weight=65;s.fly="0618";s.scream=90;多态性C_OOP的核心之一就是多态性,在C中多态性的实现可以通过函数指针的方式来实现。为简单起见,我们假设Bird结构中只有一个函数指针。structBird{void(*print)(void*p);};structfBird{structBirdp;};Bird和fBird两个结构体的打印函数实现如下:");}voidprintfBird(void*Bird){if(NULL==Bird)返回;structBird*p=(structBird*)Bird;printf("runinthefBird!!\n");}我们写一个函数来调用它们:voidprint(void*Bird){if(NULL==Bird)return;structBird*p=(structBird*)Bird;p->print(Bird);}intmain(){structBirdbird;structfBirdfbird;Bird.print=printBird;fBird.p.print=printfBird;print(&bird);//实参为Bird的对象print(&fbird);//实际参数是fBird对象return0;}它们的输出是:runintheBird!!runinthefBird!!其实这个也不难理解,不管是fBird还是Bird,它们在内存中只有一个变量,就是函数指针,而void是指任意类型的指针,当我们将其强制转换成structBird类型时,p->print自然会指向传入实参的打印地址。OOP真的那么重要吗?从大学到工作,我一直在嵌入式领域使用C语言。在学习C++的过程中,代码看的越多,代码量越大,越觉得C++对于大型软件架构的可控性很好。个性化,可读性好,便于程序员日后维护代码;我个人认为C语言最大的成功在于它的指针,但也是最容易出错的。要想看懂C,就必须掌握指针。语言虽然只是工具,却是基础。或者你可以说C太低级了。现在是OOP时代。谁会使用面向过程?别忘了操作系统是用什么写的?是C;C实现的nginx并发数是C++实现的apache的几十倍。关键是理解语言背后的思想。当然,这不是为了OOP而OOP。其实就是OOP的一些特性,比如封装、多态,其实是软件工程的思想。这些想法不区分语言。遵循这些思路可以使程序更加灵活,更容易修改和维护,避免死板、脆弱的性质。关于在嵌入式C语言中使用OOP的一些思考然而,目前来看,在嵌入式领域广泛使用C++显然是不现实的。在一个充斥着OOP的时代,为什么面向过程的C语言依然如此活跃?我们可以用它来开发一系列的小工具,而Unix/Linux就是由这些小工具组成的操作系统;同时,可以用C语言开发高性能的应用程序。C语言可移植性好,体积小,灵活,有直接与硬件打交道的指针。对内存的可操作性好,执行速度快。它是嵌入式开发的唯一高级语言。嵌入式产品的最佳选择。LW_OOPC->C语言面向对象LW_OOPC是台湾MISOO团队根据多年研发经验总结出来的可移植的面向对象C语言。虽然仅仅为我们提供足够的能力来实现所有的面向对象概念是不够的,但是我们仍然可以应用它们来完成我们简单的面向对象思想的构建。lw_oopc只用了2个文件,.h和.c文件实现了面向对象的三大要素。实现过程极其简单,技巧丰富。说白了,lw_oopc就是定义了一堆宏,使用就是调用这些宏。//|INTERFACE|接口//------------------------------------------------------------------//|CLASS|Class//-----------------------------------------------------------------//|CTOR|构造函数开始//------------------------------------------------------------------------//|END_CTOR|构造函数结束//----------------------------------------------------------------//|FUNCTION_SETTING|关联成员函数指针//----------------------------------------------------------------------//|实现|继承//-----------------------------------------------------------------------//|DTOR|为了支持析构函数的概念//|END_DTOR|//------------------------------------------------------------------//|ABS_CLASS|为了支持抽象类的概念//-----------------------------------------------------------------//|ABS_CTOR|支持可继承抽象类的构造函数//|END_ABS_CTOR|//-----------------------------------------------------------------//|EXTENDS|对于熟悉Java的人容易理解(相当于IMPLEMENTS宏)//---------------------------------------------------------------------//|SUPER_CTOR|为了支持子类调用父类的构造函数//-----------------------------------------------------------------------//|SUPER_PTR|支持向上转型//|SUPER_PTR_2|//|SUPER_PTR_3|//------------------------------------------------------------------//|SUB_PTR|支持向下转型//|SUB_PTR_2|//|SUB_PTR_3|//---------------------------------------------------------------//|INHERIT_FROM|为了支持访问直接父类的数据成员//-------------------------------------------------------------------下面是对LW_OOPC的简单分析LW_OOPC概述总之,它主要是一个头文件,我们通过使用这个头文件来实现面向对象。//lw_oopc.h:MISOO团队设计的C宏#include#ifndefLW_OOPC#defineLW_OOPC#defineCLASS(type)/typedefstructtypetype;/structtype#defineCTOR(type)/void*type##New()/{/structtype*t;/t=(structtype*)malloc(sizeof(structtype));#defineCTOR2(type,type2)/void*type2##New()/{/structtype*t;/t=(structtype*)malloc(sizeof(structtype));#defineEND_CTORreturn(void*)t;}#defineFUNCTION_SETTING(f1,f2)t->f1=f2;#defineIMPLEMENTS(type)structtypetype#defineINTERFACE(type)structtype#endif/*lw_oopc.h*/下面一段代码是简单的OOPC应用程序://Circle.c#include#include"lw_oop.h"#definePI3.1415926CLASS(Circle){double(*cal_area)(double);}doublecircle_cal_area(doubleradius){returnPI*r*r;}CTOR(Circle)FUNCTION_SETTING(cal_area,circle_cal_area)END_CTORintmain(){doublearea=0.0;Circle*pc;pc=(Circle*)CircleNew();area=pc->cal_area(10);printf("area=%f/n",area);return0;}接口的实现在OOP程序中通常是通过类定义和接口定义来实现的。//IA.h#include"lw_oopc.h"INTERFACE(IA){void(*init)(void*,double);double(*cal_area)(void*);double(*cal_permimeter)(void*);}//circle.c#include"IA.h"#definePI3.1415926CLASS(Circle){IMPLEMENTS(IA);doubleradius;}staticvoidcircle_init(void*circle,doubleradius){Circle*_this=(Circle*)circle;_this->radiusradius=radius;}staticdoublecircle_cal_area(void*circle){Circle*_this=(Circle*)circle;returnPI*_this->radius*_this->radius;}staticdoublecircle_cal_permimeter(void*circle){Circle*_this=(Circle*)circle;return2*PI*_this->radius;}CTOR(Circle)FUNCTION_SETTING(IA.init,circle_init)FUNCTION_SETTING(IA.cal_area,circle_cal_area)FUNCTION_SETTING(IA.cal_permimeter,circle_cal_permimeter)END_CTOR//main.c#include#include"IA.h"voidprint_area(IA*pi){printf("area=%f/n",pi->cal_area(pi));}intmain(){IA*pc=NULL;pc=(IA*)CircleNew();pc->init(pc,10.0);print_area();return0;}求和向上,语言只是工具,任何语言都是相通的,关键是要理解语言背后的思维。了解它的想法,任何语言,随便用。语言没有好坏之分。任何一种语言既然存在,自然就有其存在的价值。