函式多載(Function Overloading)是 C++ 的核心特性之一,允許在同一作用域內定義多個同名但參數列表不同的函式。編譯器根據呼叫時提供的實參類型、個數、順序,自動選擇最匹配的函式版本。這不僅減少了命名負擔,更讓介面設計更符合直覺。
當一組函式執行邏輯相同的操作(如「取最大值」、「排序」、「序列化」),但作用於不同資料型態(int、vector、Matrix)時,多載是最佳選擇。
// 傳統命名:使用者必須記住三個不同函式名
int max_int(int a, int b);
int max_vector(const vector<int>& v);
int max_matrix(const Matrix& m);
// 多載命名:統一介面,編譯器自動分派
int Max(int a, int b);
int Max(const vector<int>& v);
int Max(const Matrix& m);
若函式雖然名稱相關,但語意本質不同,或參數列表相同導致無法區分,則不應強行多載。例如游標控制函式:
// 錯誤示範:全名為 Move,呼叫端無法直觀理解方向
Screen& Move(); // 向上?向下?還是重置?
// 正確做法:使用語意明確的命名
Screen& MoveUp();
Screen& MoveDown();
Screen& MoveLeft();
Screen& MoveRight();
當呼叫 S(2.4) 面對多個候選函式時,編譯器執行嚴格的三步驟決議:
收集同名且可見的所有函式。範例中 S()、S(int)、S(double, double=1.2)、S(const char*, const char*) 皆為候選,Max(int,int) 因名稱不同被排除。
從候選集中挑選參數個數相容(含預設參數)且實參可隱含轉換為形參的函式。範例中 S(int)(double→int 收縮轉換)與 S(double, double)(第二參數用預設值,第一參數完全匹配)為可行函式。
依據標準轉換序列等級評分:
精確匹配 > 提升 > 標準轉換 > 使用者定義轉換 > 省略號。
範例中 S(double, double) 需零轉換(含預設參數),優於 S(int) 的 double→int 收縮轉換,故編譯器選擇前者。
void f(int) 與 void f(const int&) 參數列表視為相同,無法多載。explicit 防止非預期轉換: 建構子若非刻意設計隱含轉換,應標記 explicit,減少多載決議的驚喜。函式多載是 C++ 介面設計的利器,核心原則是「語意一致、型態多態」。深入理解編譯器的三階段決議機制,能幫助開發者避開模糊呼叫、隱含轉換陷阱,設計出既直觀又型別安全的 API。