面向對象這個概念和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后並沒有減少你的代碼量,而是增加了不少。但用它的目的並非是減少體力輸出,而是對軟件結構的一種改良。
各個宏的真實面目留待下一篇揭露。
