首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 內聯函數、默認參數、占位參數與函數重載完全指南

     編輯:關於C++

內聯函數:用編譯器展開換調用開銷

語法與原理


inline int min(int a, int b) { return a < b ? a : b; }
// 編譯器可能將調用點直接替換為函數體,省去壓棧/跳轉/返回開銷

關鍵規則

  • inline **必須與函數定義放在一起** (通常在頭文件),否則編譯器忽略請求。
  • 只是**建議**,編譯器可拒絕 (函數過大、含循環/遞歸/虛函數調用、取地址等)。
  • 現代編譯器 (GCC/Clang/MSVC -O2) 會自動內聯簡單函數,無需關鍵字;__attribute__((always_inline)) 可強制 (GCC/Clang)。
  • C++17 constexpr 隱含內聯語義,且保證編譯期可計算。

對比宏

特性內聯函數宏 (#define)
類型檢查是無 (文本替換)
副作用無 (參數求值一次)有 (如 MIN(++a,b) 導致 a 增兩次)
調試可設置斷點、查看變量不可調試
作用域遵循 C++ 作用域規則全局文本替換

結論:完全替代宏定義函數片段,拒絕 #define 實現邏輯。

默認參數:簡化調用、減少重載


void connect(string host, int port = 80, int timeout = 3000);
// 調用: connect("localhost"); connect("api.com", 443); connect("svc", 8080, 5000);

規則

  1. 只有**尾部參數**可有默認值,一旦開始必須連續到最後。
  2. 聲明處給默認值 (頭文件),定義處**不再重複** (否則重複定義錯誤)。
  3. 虛函數默認參數**靜態綁定** (按靜態類型決定),派生類覆蓋時建議不重複默認值,避免驚訝行為。

占位參數:佔位兼容、未來擴展


void callback(int /*event*/, void* /*data*/) { /* 當前不需要參數,但介面預留 */ }
// 或
void func(int, double = 3.14); // 僅聲明類型,無參數名
  • 函數體內**無法使用**無名參數。
  • 常用於:回調介面統一、預留擴展位、適配舊版本簽名。

函數重載:同名不同參數的多態

重載條件 (至少滿足一項)

  1. 參數個數不同
  2. 參數類型不同
  3. 參數順序不同 (如 f(int, double) vs f(double, int))

返回類型、cv 資格、異常規範不能作為重載依據。

重載解析規則 (按優先級)

  1. 精確匹配 (含隱式轉換:T→T&, T→const T&, 數組/函數退化、bool 提升、整數提升)。
  2. 通過默認參數匹配。
  3. 標準轉換 (算術轉換、指針轉換、派生→基類)。
  4. 用戶定義轉換 (構造函數/轉換運算符)。
  5. 省略號 ... 匹配。

**二義性** → 編譯錯誤;**無可行函數** → 編譯錯誤。

重載與函數指針


int f(int); int f(double);
int (*p1)(int) = f;   // 精確匹配 f(int)
int (*p2)(double) = f; // 精確匹配 f(double)
// int (*p3)(...) = f; // 錯誤:二義性

賦值時按指針類型從重載集選擇匹配者。

最佳實踐總結

  1. 簡單高頻函數用 inline (或 constexpr),複雜邏輯交給編譯器優化器。
  2. 默認參數減少重載數量,但虛函數慎用。
  3. 重載表達語義一致的操作 (如 print(int)/print(string)),語義不同請用不同名。
  4. 避免「參數類型隱式轉換導致意外重載選中」 (如 f(int)/f(double) 調用 f(3.14f) 選 double 版),必要時用 explicit 構造或刪除不想要的重載 (=delete)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved