C 語言無原生閉包或委派,但透過函式指標作為結構體成員,即可實現「註冊回調 → 觸發執行」模式,廣泛用於事件驅動、驅動程式、GUI 框架。
#include
// 1. 定義回調函式簽名
typedef void (*CallbackFunc)(const char* message);
// 2. 結構體持有函式指標
typedef struct {
CallbackFunc callback; // 回調槽位
void* user_data; // 可選:使用者上下文
} EventHandler;
// 3. 具體回調實作
void onEvent(const char* msg) {
printf("[Event] %s\n", msg);
}
void onError(const char* msg) {
fprintf(stderr, "[ERROR] %s\n", msg);
}
// 4. 觸發器:檢查非 NULL 後呼叫
void triggerEvent(EventHandler* handler, const char* msg) {
if (handler && handler->callback) {
handler->callback(msg);
}
}
int main() {
EventHandler h1 = { .callback = onEvent };
EventHandler h2 = { .callback = onError };
triggerEvent(&h1, "System started");
triggerEvent(&h2, "Disk full");
// 動態切換回調
h1.callback = onError;
triggerEvent(&h1, "Switched to error handler");
return 0;
}
typedef struct {
int id;
char name[32];
} Sensor;
void sensorCallback(const char* msg, void* ctx) {
Sensor* s = (Sensor*)ctx;
printf("[Sensor %d:%s] %s\n", s->id, s->name, msg);
}
typedef struct {
void (*callback)(const char*, void*);
void* user_data;
} CallbackWithContext;
int main() {
Sensor s1 = {1, "Temp"};
CallbackWithContext cb = {sensorCallback, &s1};
cb.callback("Reading: 25.6°C", cb.user_data);
return 0;
}
#define MAX_HANDLERS 10
typedef struct {
int event_type;
EventHandler handlers[MAX_HANDLERS];
int count;
} EventDispatcher;
void dispatch(EventDispatcher* disp, int type, const char* msg) {
for (int i = 0; i < disp->count; i++) {
if (disp->handlers[i].callback) // 簡易:同類型全觸發
disp->handlers[i].callback(msg);
}
}
// 註冊
int subscribe(EventDispatcher* disp, int type, CallbackFunc cb) {
if (disp->count >= MAX_HANDLERS) return -1;
disp->handlers[disp->count++] = (EventHandler){cb, NULL};
return 0;
}
C++11 後推薦使用型別安全、支援捕獲的 std::function:
#include
#include
#include
class EventBus {
using Handler = std::function;
std::vector handlers_;
public:
void subscribe(Handler h) { handlers_.push_back(std::move(h)); }
void publish(const std::string& msg) {
for (auto& h : handlers_) if (h) h(msg);
}
};
int main() {
EventBus bus;
bus.subscribe([](auto msg){ std::cout << "[Lambda] " << msg << "\n"; });
bus.subscribe([](auto msg){ std::cerr << "[Error] " << msg << "\n"; });
bus.publish("Hello Callback");
return 0;
}
| 特性 | C 函式指標 | C++ std::function |
|---|---|---|
| 型別安全 | 靠開發者簽名一致 | 編譯期強制檢查 |
| 狀態捕獲 | 需手動傳 void* | Lambda 自動捕獲 |
| 效能 | 極低開銷 (單指標) | 小型物件優化,略高 |
| 可攜性 | 純 C89 相容 | 需 C++11 |
「結構體 + 函式指標」是 C 語言實現回調/多型的基石模式。理解其機制有助於閱讀 Linux 核心、嵌入式驅動、GUI 庫 (GTK/Qt 早期) 代碼。C++ 專案應優先使用 std::function,但在與 C 介面互操作、極度資源受限環境,C 風格回調仍是最佳選擇。