同一作用域內宣告多個**同名**函式,但**參數列表不同**(類型、個數、順序),編譯器根據實參型別自動選擇最匹配版本。返回類型**不能**作為多載依據。
int test(int a, int b) { return a + b; }
float test(float a, float b) { return a + b; }
// 呼叫 test(1,2) → 呼叫 int 版
// 呼叫 test(2.1f,3.14f) → 呼叫 float 版
C++ 編譯器將函式簽名編碼進修飾名稱(Name Mangling),例如:
test(int,int) → ?test@@YAHHH@Z (MSVC) / _Z4testii (GCC/Clang)test(float,float) → ?test@@YAMMM@Z / _Z4testff連結器看到的是不同符號,無衝突。程式設計師**無需關心**修飾細節,但理解其存在有助於解決連結錯誤(如 extern "C" 關閉修飾)。
char→int, float→double, derived*→base* 等標準轉換。... 最低優先級。若多個候選同級 → **模糊呼叫** 編譯錯誤。
| 陷阱 | 現象 | 解決 |
|---|---|---|
| 預設參數造成模糊 | void f(int); void f(int, int=0); f(1); → 模糊 | 避免同名函式使用預設參數,或合併為單一函式 |
| 傳遞字面常數 0 給指標/整數多載 | void f(int); void f(char*); f(0); → 呼叫 int 版(0 是 int) | 用 nullptr (C++11) 明確指標意圖 |
| const 引用 vs 非 const 引用 | void f(int&); void f(const int&); int x; f(x); → 呼叫非 const 版 | 理解非 const 引用優先綁定非 const 左值 |
| 範本與非範本多載 | template<T> void f(T); void f(int); f(1); → 呼叫非範本版(較特化) | 預期行為,無需干預 |
print(int), print(string) 皆為列印)。print_int, print_str)或單一函式配合 std::variant/多態。void draw(int x, int y, Color c = Color::Black))。std::function / Lambda 多載集合(需手動解析)。using 宣告引入基類多載至衍生類作用域(using Base::foo;)。函式多載是 C++ 靜態多態的基石。掌握解析規則、名稱修飾原理、常見模糊情境,能設計出直觀、型別安全的 API。記住:**多載是為了呼叫端便利,而非實作者炫技**——若增加認知負擔,請改用不同名稱。