extends 宏/* oosm.h 片段 */
#define extends(type) type type /* 結構體首欄位嵌入父類型別 */
展開後:struct Child { Parent Parent; ... };
子類實例開頭即為父類實例 → 指標相容性:Child* 隱式轉換為 Parent*。
/* csqua.h */
#ifndef __CSQUA_H__
#define __CSQUA_H__
#include "crect.h"
class(csqua) {
extends(crect); // 單一繼承:嵌入 crect
};
#endif
記憶體佈局:
csqua 實例: +------------------+ | crect (父類) | ← 偏移量 0 | imeas | (介面繼承自 crect) | width | | height | +------------------+ | (csqua 無新增欄位) | +------------------+
csqua.c#include "csqua.h"
static double peri(void* this) {
crect* r = (crect*)this; // 關鍵:this 實為 crect*
return 4 * r->width; // 正方形周長 = 4 * 邊長
}
static double area(void* this) {
crect* r = (crect*)this;
return r->width * r->width; // 面積 = 邊長²
}
constructor(csqua) {
/* 覆寫父類介面方法 */
mapping(crect.imeas.peri, peri);
mapping(crect.imeas.area, area);
}
destructor(csqua) {
return 1;
}
| 關鍵點 | 說明 |
|---|---|
this 型別 | 建構子中 this 為 csqua*,但 extends 使其首欄位為 crect,轉型為 crect* 存取 width/height |
| 介面繼承 | csqua 自動擁有 imeas (來自 crect),無需重複 implements |
| 方法覆寫 | mapping(crect.imeas.peri, peri) 直接覆蓋父類建構子中綁定的函數指標 |
| 建構順序 | OOSM 僅呼叫 csqua_constructor,不自動呼叫父類建構子 → 子類建構子需完全負責初始化(含介面綁定) |
#include
#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; // 存取繼承欄位:s->crect.width
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;
}
Circle: 直徑=18.46 周長=57.99 面積=267.35 Rectangle: 周長=203.26 面積=1813.73 Square: 周長=800.00 面積=40000.00
| 篇章 | 核心內容 | 關鍵宏 |
|---|---|---|
| (一) 核心架構 | 宏包定義、類別/介面/建構/解構/映射 | class interface constructor destructor mapping |
| (二) 介面多態 | imeas 介面、crect/ccirc 實作、void* 多態 | implements interface |
| (三) 單一繼承 | extends(crect)、csqua 覆寫、記憶體佈局 | extends |
this 傳遞 + 宏語法糖private/protected)this 傳遞冗長 (c->imeas.peri(c))implements 遞增偏移量parent_constructor(this) 呼叫destroy,解構子鏈式調用get_width/set_width 封裝欄位面向對象是思想,非語言專利。C 語言以最樸素方式揭示了封裝、繼承、多態的機械本質——這正是理解任何 OO 語言底層運作的鑰匙。