lw_oopc (Lightweight OOP in C) 僅兩個檔案 (lw_oopc.h, lw_oopc.c) 實現封裝、繼承、多態,核心是宏定義的「類描述表」與實例結構體。
// 類描述表
typedef struct Class {
size_t size; // 實例大小
void (*ctor)(void*); // 建構函數
void (*dtor)(void*); // 解構函數
// ... 可擴展虛函數指標
} Class;
// 實例首欄位必為 Class 指標
#define SUPER_PTR(obj, SuperType) ((SuperType*)((char*)(obj) + offsetof(SubType, super)))
// 定義類宏 (簡化版)
#define CLASS(Type) \
typedef struct Type { const Class *class; } Type; \
extern const Class Type##_class;
// 實現宏
#define IMPLEMENT(Type, Super) \
const Class Type##_class = { sizeof(Type), Type##_ctor, Type##_dtor }; \
void Type##_ctor(void *self) { ... }
/* 抽象基類 Animal */
CLASS(Animal)
#define ANIMAL_METHODS \
void (*Eat)(Animal*); \
int age;
#define Animal_Init(self) ...
/* 子類 Dog */
CLASS(Dog)
#define Dog_Init(self) { \
Animal_Init(self); \
((Dog*)self)->Eat = Dog_Eat; \
}
void Dog_Eat(Animal *a) { printf("Dog eating\n";) }
/* 子類 Bird */
CLASS(Bird)
#define Bird_Init(self) { \
Animal_Init(self); \
((Bird*)self)->Fly = Bird_Fly; \
}
void Bird_Fly(Bird *b) { printf("Bird flying\n";) }
void Bird_Eat(Animal *a) { printf("Bird eating\n";) }
Dog *dog = malloc(sizeof(Dog));
Dog_Init(dog);
dog->Eat(dog); // 自身方法
Bird *bird = malloc(sizeof(Bird));
Bird_Init(bird);
bird->Fly(bird); // 自身方法
((Animal*)bird)->Eat((Animal*)bird); // 繼承方法 (需轉型)
/* 或使用宏 */
SUPER_PTR(bird, Animal)->Eat(SUPER_PTR(bird, Animal));
| 優點 | 缺點 |
|---|---|
| 極輕量,無外部依賴 | 宏大量使用,除錯困難 |
| 多重繼承不支援 | |
| 記憶體佈局透明,易與 C++ 互操作 | 建構/解構需手動管理 |
| 理解 C++ 物件模型最佳教具 | 宏錯誤訊息晦澀 |
閱讀 lw_oopc 源碼能深入理解:
lw_oopc 是 C 語言實現 OOP 的極簡典範,適合想一窺「類與虛函數底層真相」的開發者研讀。