/* Object-Oriented Support Macros (OOSM)
* 輕量級 C 面向對象支援宏包
* 參考 LW_OOPC 精簡而來
*/
#ifndef __OOSM_H__
#define __OOSM_H__
#include <stdlib.h>
/* ===== 類別定義 ===== */
#define class(type) \
typedef struct type type; \
type* type##_new(void); \
void type##_constructor(type* t); \
int type##_destructor(type* t); \
void type##_delete(type* t); \
struct type
#define interface(type) \
typedef struct type type; \
struct type
/* ===== 繼承與實現 ===== */
#define extends(type) type type // 繼承:嵌入父類結構體
#define implements(type) type type // 實現介面:同樣嵌入
/* ===== 建構子/解構子宏 ===== */
#define constructor(type) \
type* type##_new(void) { \
type* this = (type*)malloc(sizeof(type)); \
if (!this) return NULL; \
type##_constructor(this); \
return this; \
} \
void type##_constructor(type* this)
#define destructor(type) \
void type##_delete(type* this) { \
if (type##_destructor(this)) free(this); \
} \
int type##_destructor(type* this)
/* ===== 方法映射 ===== */
#define mapping(tf, sf) this->tf = sf
#endif /* __OOSM_H__ */
/* 使用 OOSM 定義 */
class(Circle) {
implements(IShape); // 實現介面
double radius;
double (*area)(Circle* this); // 自有方法
};
/* 展開後等價於 */
typedef struct Circle Circle;
Circle* Circle_new(void);
void Circle_constructor(Circle* t);
int Circle_destructor(Circle* t);
void Circle_delete(Circle* t);
struct Circle {
IShape IShape; // 介面嵌入
double radius;
double (*area)(Circle* this);
};
imeas.h#ifndef __IMEAS_H__
#define __IMEAS_H__
#include "oosm.h"
interface(imeas) {
double (*peri)(void* this); // 周長
double (*area)(void* this); // 面積
};
#endif
關鍵點:介面方法第一參數用 void*,便於不同子類 this 指標隱式轉換。
crect.h / crect.c/* crect.h */
#ifndef __CRECT_H__
#define __CRECT_H__
#include "imeas.h"
class(crect) {
implements(imeas);
double width;
double height;
};
#endif
/* crect.c */
#include "crect.h"
static double peri(void* this) {
crect* r = (crect*)this;
return 2 * (r->width + r->height);
}
static double area(void* this) {
crect* r = (crect*)this;
return r->width * r->height;
}
constructor(crect) {
mapping(imeas.peri, peri);
mapping(imeas.area, area);
}
destructor(crect) {
return 1; // 回傳 1 表示釋放記憶體
}
#include <stdio.h>
#include "imeas.h"
#include "ccirc.h"
#include "crect.h"
#include "csqua.h"
int main() {
ccirc* c = ccirc_new();
crect* r = crect_new();
csqua* s = csqua_new();
c->radius = 9.23;
r->width = 23.09; r->height = 78.54;
s->crect.width = 200.00; // 繼承自 crect
/* 多態呼叫:介面方法統一入口 */
printf("Circle: 直徑=%.2f 周長=%.2f 面積=%.2f\n",
c->diam(c), c->imeas.peri(c), c->imeas.area(c));
printf("Rectangle: 周長=%.2f 面積=%.2f\n",
r->imeas.peri(r), r->imeas.area(r));
printf("Square: 周長=%.2f 面積=%.2f\n",
s->crect.imeas.peri(s), s->crect.imeas.area(s));
ccirc_delete(c);
crect_delete(r);
csqua_delete(s);
return 0;
}
| 機制 | C++ 對應 | OOSM 實現 |
|---|---|---|
| 封裝 | class + private | 結構體 + 紀律性命名(慣例 `_` 開頭) |
| 繼承 | class Derived : Base | extends(Base) → 結構體首欄位嵌入父類 |
| 多態 | virtual 函數 + vtable | 函數指標欄位 + mapping 手動綁定 |
| 建構/解構 | ctor/dtor | constructor/destructor 宏生成 _new/_delete |
| 介面 | abstract class | interface + implements 嵌入 |
private,靠命名慣例與程式碼審查c->imeas.peri(c) 需顯式傳 thisextends 僅支援單一父類setjmp/longjmp