設計模式(如 Bridge、Proxy、Factory)的核心在於「抽象」。面向對象編程透過抽象類別建立框架骨架,再配合多態實現具體行為。C++ 原生支援繼承與虛函數,使這類設計極為自然;但純 C 語言缺乏語言級別的多態支援,許多開發者因此放棄此類設計思路。事實上,C 語言完全可以手動實現多態機制——關鍵在於理解虛函數表(vtable)的本質,並用結構體與函數指針加以模擬。
在 Visual C++ 中,__interface 關鍵字實際上被定義為 struct:
#ifndef Interface
#define Interface struct
#endif
當一個類別包含虛函數時,編譯器會在物件開頭植入一個隱藏指標 vptr,指向該類別的虛函數表(vtable)——一個由函數指標組成的陣列。C++ 只是在語言層面自動完成了這一切;在 C 中,我們只需手動構建相同的資料結構即可。
使用結構體封裝一組函數指標,即可形成一個介面契約:
typedef struct {
void (*Foo1)(void);
char (*Foo2)(void);
char* (*Foo3)(char* str);
} MyVirtualInterface;
主類別 DoMyAct 不關心具體實現,僅持有介面指標並委派呼叫:
typedef struct {
MyVirtualInterface* m_pInterface;
} DoMyAct;
void DoMyAct_SetInterface(DoMyAct* self, MyVirtualInterface* pInterface) {
self->m_pInterface = pInterface;
}
void DoMyAct_Do(DoMyAct* self) {
if (!self->m_pInterface) return;
self->m_pInterface->Foo1();
char c = self->m_pInterface->Foo2();
// 進一步處理...
}
每個具體類別內含一個介面陣列(可視為物件池),並提供建構函數初始化函數指標:
#define MAX_INSTANCES 10
typedef struct {
MyVirtualInterface vtable[MAX_INSTANCES];
int used[MAX_INSTANCES];
} Act1;
MyVirtualInterface* Act1_CreateInterface(Act1* self) {
for (int i = 0; i < MAX_INSTANCES; ++i) {
if (!self->used[i]) {
self->used[i] = 1;
self->vtable[i].Foo1 = Act1_Foo1_Impl;
self->vtable[i].Foo2 = Act1_Foo2_Impl;
self->vtable[i].Foo3 = Act1_Foo3_Impl;
return &self->vtable[i];
}
}
return NULL; // 池滿
}
// 具體實現函數
void Act1_Foo1_Impl(void) { /* ... */ }
char Act1_Foo2_Impl(void) { return 'A'; }
char* Act1_Foo3_Impl(char* str) { return str; }
Act2 結構與邏輯完全相同,僅實現函數不同。
主迴圈只需操作介面指標,完全解耦具體類型:
int main(void) {
DoMyAct actor = {0};
Act1 act1Pool = {0};
Act2 act2Pool = {0};
MyVirtualInterface* list[20];
int count = 0;
// 動態註冊實例
MyVirtualInterface* p;
if ((p = Act1_CreateInterface(&act1Pool))) list[count++] = p;
if ((p = Act2_CreateInterface(&act2Pool))) list[count++] = p;
// 統一調度
for (int i = 0; i < count; ++i) {
DoMyAct_SetInterface(&actor, list[i]);
DoMyAct_Do(&actor); // 具體行為由介面決定
}
// 釋放資源...
return 0;
}
這種「結構體+函數指標」模式本質上是手工構建 vtable,實現了:
雖然 C 語言缺乏語法糖,但理解其底層機制後,同樣能寫出具備良好擴展性的框架式代碼。這不僅是技巧,更是對「組合優於繼承」原則的深度實踐。