C++ 編譯器透過名稱修飾 將同名函數編碼為唯一符號 (含參數型別、數量、命名空間),實現編譯期靜態分派。C 無此機制,需手動模擬。
int func1(void) { return 1; }
int func2(void) { return 2; }
int (*func)(void); // 函數指標
void dispatch(int selector) {
if (selector == 0) func = func1;
else func = func2;
int result = func(); // 間接呼叫
}
缺點:執行期分派、型別不安全、需手動管理選擇邏輯。
int (*dispatch_table[2])(void) = { func1, func2 };
int call(int index) {
if (index >= 0 && index < 2)
return dispatch_table[index]();
return -1; // 錯誤
}
#define ADD(x, y) _Generic((x), \
int: add_int, \
double: add_double, \
float: add_float \
)(x, y)
int add_int(int a, int b) { return a + b; }
double add_double(double a, double b) { return a + b; }
float add_float(float a, float b) { return a + b; }
// 使用
int i = ADD(1, 2); // 呼叫 add_int
double d = ADD(1.0, 2.0); // 呼叫 add_double
C11 _Generic 選擇關聯式,提供編譯期類別型重載,無執行期開銷,型別安全。
| 維度 | C++ 重載 | C 模擬 |
|---|---|---|
| 分派時機 | 編譯期 (靜態) | 執行期 (函數指標) / 編譯期 (_Generic) |
| 型別安全 | 完整 | 函數指標無、_Generic 有 |
| 返回型別區分 | 不支援 | 不支援 |
| 預設參數 | 支援 | 需手動模擬 |
| 模板/泛型 | 支援 | 無 |
| 名稱修飾 | 自動 | 手動命名區分 |
_Generic (C11) 或不同上綴命名 (add_int, add_double)extern "C" 函數,避免名稱修飾理解 C++ 重載底層機制 (名稱修飾、靜態分派),有助於設計 C 介面、實作動態分派、進行混合語言開發。