允許在同一作用域內宣告多個**同名**函數,只要**參數列表不同**(型別、個數、順序),編譯器即視為不同函數。返回型別**不能**作為多載區分依據。
// C 風格:不得不起不同名字
int add_int(int a, int b);
float add_float(float a, float b);
double add_double(double a, double b);
// C++ 多載:統一語意名稱
int add(int a, int b);
float add(float a, float b);
double add(double a, double b);
std::cout << int / << double / << const char*)。const/volatile/引用)。int → double、float → double、char → int)。... 最低優先級。若多個候選函數經過最佳轉換序列後仍同優,編譯器報**二義性錯誤**。
int foo(); // 錯誤:重複宣告
double foo();
void print(int a);
void print(int a, int b = 10);
print(5); // 二義性:匹配第一個 或 第二個用預設值
void process(int a, double b);
void process(double a, int b); // 順序不同,合法
process(1, 2.0); // 呼叫第一個
process(1.0, 2); // 呼叫第二個
void func(int &); // 綁定左值
void func(const int &); // 綁定右值/const 左值
void func(int &&); // C++11 移動語意,綁定右值
int x = 10;
func(x); // 呼叫 int&
func(10); // 呼叫 const int&
func(std::move(x)); // 呼叫 int&&
編譯器將函數簽名編碼進符號表,例如 MSVC:
int add(int, int) → ?add@@YAHHH@Z
float add(float, float) → ?add@@YAMMM@Z
這就是連結器能區分同名函數的原因,也解釋為什麼 C++ 庫不能直接被 C 程式呼叫(需 extern "C" 關閉修飾)。
open(file) vs open(socket) 應用不同名)。template<typename T> T add(T a, T b) 可替代多個算術型別多載,且支援使用者自訂型別。const 引用、右值引用多載提升效能與正確性(避免不必要複製、支援移動語意)。