函式
函數是 C++ 的實體,它將一系列 語句(即函數體)與一個名稱以及零個或多個 函數參數 關聯起來。
// function name: "isodd" // parameter list has one parameter, with name "n" and type int // the return type is bool bool isodd(int n) { // the body of the function begins return n % 2; } // the body of the function ends
當呼叫函數時(例如在 函數呼叫表達式 中),參數會根據引數(在呼叫處提供或使用 預設值)進行初始化,隨後執行函數體中的語句。如果 參數列表 以 ... 結尾,則可以向函數傳遞額外的引數,這類函數被稱為 可變參數函數 (variadic function)。
int main() { for (int arg : {-3, -2, -1, 0, 1, 2, 3}) std::cout << isodd(arg) << ' '; // isodd called 7 times, each // time n is copy-initialized from arg }
函數呼叫表達式中的 非限定 函數名稱會透過一套稱為 「依賴引數名稱查找」(Argument-Dependent Lookup, ADL) 的額外規則進行查找。
函數可以透過 return 語句終止,或透過 丟擲 (throwing) 一個 異常 來終止。
|
函數可以是 協程 (coroutine),在這種情況下,它可以暫停執行並在稍後恢復。 |
(自 C++20 起) |
函數 宣告 可以出現在任何作用域中,但函數 定義 只能出現在命名空間作用域,或是(對於 成員 和 友元 函數)類別作用域中。在類別體中宣告且未標記為 friend 的函數是類別成員函數。這類函數具有許多額外屬性,詳情請參閱 成員函數。
函數不是物件:不存在函數陣列,且函數不能透過值傳遞或從其他函數回傳。指向函數的指標和參考(main 函數 除外,以及 大多數標準庫函數(C++20 起))是允許的,並且可以用在這些函數本身無法使用的場合。因此,我們稱這些函數是「可定址的 (addressable)」。
每個函數都有一個類型,該類型由函數的回傳類型、所有參數的類型(經過陣列到指標以及函數到指標轉換後,參見 參數列表)、函數是否為 noexcept(C++17 起),以及對於非靜態成員函數,cv 限定符與引用限定符(C++11 起)組成。函數類型也具有 語言連結 (language linkage)。不存在 cv 限定的函數類型(不要與 cv 限定的函數 混淆,例如 int f() const;,也不要與回傳 cv 限定類型 的函數混淆,例如 std::string const f();)。如果將 cv 限定符添加到函數類型的別名中,該限定符將會被忽略。
同一作用域內的多個函數可以擁有相同的名稱,只要它們的參數列表以及(對於非靜態成員函數)cv/ref(C++11 起) 限定符不同即可。這被稱為 函數多載 (function overloading)。僅在回傳類型及 noexcept 規格(C++17 起)上有所區別的函數宣告無法進行多載。多載函數的位址 確定方式有所不同。
|
C++ 使用 lambda 表達式 來實現 匿名函數。 |
(C++11 起) |
[編輯] 函數物件 (Function objects)
除了函數左值外,函數呼叫表達式還支援函數指標,以及任何重載了函數呼叫運算子或可轉換為函數指標的類別類型值(包括 lambda 表達式)(C++11 起)。這些類型統稱為 函數物件 (FunctionObjects),它們在 C++ 標準庫中被廣泛使用,例如參見 BinaryPredicate 和 Compare 的用法。
標準庫還提供了許多預定義的 函數物件模板 以及組合新函數物件的方法(包括 std::less, std::mem_fn, std::bind, std::function(C++11 起), std::not_fn(C++17 起), std::bind_front(C++20 起), std::bind_back, std::move_only_function(C++23 起), std::copyable_function, 以及 std::function_ref(C++26 起))。