面向对象这个概念和C语言似乎是无缘的,但如果你真的很想用怎么办?幸运的是有人和你的想法一样,并且做出了实实在在的东西。我了解的比较多的是lw_oopc和ooc两个东东。
ooc全称objective oriented c,作者做了大量的工作实现了c语言的封装、多态、继承这三种面向对象特征,还实现了所谓的虚函数。老实说,我对ooc的作者佩服的五体投地,能把c语言玩到这个程度非常了得了。ooc的文档工作做的也不错,但看了它的doc之后,还是觉得用起来有些麻烦。于是,又去google之,最终找到lw_oopc这个好东东。
lw_oopc仅用了2个文件,.h及.c文件就实现了面向对象的三大因素,实现过程极为简洁又富含技巧。lw_oopc说白了,就是定义了一堆宏,使用起来也就是调用这些宏。
//| INTERFACE | 接口 //---------------------------------------------------------------------- //| CLASS | 类 //---------------------------------------------------------------------- //| CTOR | 构造器开始 //---------------------------------------------------------------------- //| END_CTOR | 构造器截止 //---------------------------------------------------------------------- //| FUNCTION_SETTING | 关联成员函数指针 //---------------------------------------------------------------------- //| IMPLEMENTS | 继承 //----------------------------------------------------------------------
//| 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做一个‘类’是怎样的。
————————————————————————————————————————————
设计一个抽象类:Animal,属性有:age,方法有:eat
继承Animal,设计一个类:Dog,实现其方法
继承Animal,设计一个类:Bird,增加方法:Fly
代码如下所示:
*********************************************************** #include <stdio.h> #include "lw_oopc.h" ******************************** /* Animal */ ABS_CLASS(Animal) { int age; void (*Init)(Animal*); void (*Eat)(Animal*); }; static void Animal_Init(Animal* me) { me->age = 0; } static void Animal_Eat(Animal* me) { printf("Animal eat.\r\n"); } ABS_CTOR(Animal) FUNCTION_SETTING(Init, Animal_Init); FUNCTION_SETTING(Eat, Animal_Eat); END_ABS_CTOR ******************************** /* Dog */ CLASS(Dog) { EXTENDS(Animal); void (*Init)(Dog*); }; static void Dog_Init(Dog* me) { SUPER_PTR(me, Animal)->Init(SUPER_PTR(me, Animal)); } static void Dog_Eat(Animal* me) { printf("Dog eat.\r\n"); } CTOR(Dog) SUPER_CTOR(Animal); FUNCTION_SETTING(Init, Dog_Init); FUNCTION_SETTING(Animal.Eat, Dog_Eat); END_CTOR ******************************** /* Bird */ CLASS(Bird) { EXTENDS(Bird); void (*Init)(Bird*); void (*Fly)(Bird*); }; static void Bird_Init(Bird* me) { SUPER_PTR(me, Animal)->Init(SUPER_PTR(me, Animal)); } static void Bird_Fly(Bird* me) { printf("Bird fly.\r\n"); } static void Bird_Eat(Animal* me) { printf("Bird eat.\r\n"); } CTOR(Bird) SUPER_CTOR(Animal); FUNCTION_SETTING(Init, Bird_Init); FUNCTION_SETTING(Animal.Eat, Bird_Eat); FUNCTION_SETTING(Fly, Bird_Fly); END_CTOR
有了这些定义,用起来就跟简单c++的类一样了,只是定义一个类的实例时应采用如下一种格式:
Dog* dog = Dog_new();
dog->Init(dog);
调用自身的方法:
Bird* bird = Bird_new(); bird->Init(bird); bird->Fly(bird);
调用继承的方法稍显麻烦:
((Animal*)bird)->Eat((Animal*)bird);
或者当EXTENDS语句在定义类时并不在第一句(下一篇将揭露各个宏的真实面目)时,最稳妥也显得繁琐一点的方式为:
SUPER_PTR(bird, Animal)->Eat(SUPER_PTR(bird, Animal));
是不是有那么点意思,抽象、继承、多态几个概念都包含了。同样能看出,用了lw_oopc后并没有减少你的代码量,而是增加了不少。但用它的目的并非是减少体力输出,而是对软件结构的一种改良。
各个宏的真实面目留待下一篇揭露。