函式
函式是 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
當函式被呼叫時,例如在函式呼叫表示式中,引數會從實參(在呼叫位置提供或預設化)初始化,然後執行函式體中的語句。如果引數列表以...結尾,則可以向函式提供額外的實參,這種函式稱為可變引數函式。
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 }
非限定函式名在函式呼叫表示式中透過一組額外的規則查詢,這些規則稱為“實參依賴查詢”(ADL)。
函式可以是協程,在這種情況下它可以暫停執行以便以後恢復。 |
(C++20 起) |
函式宣告可以出現在任何作用域中,但函式定義只能出現在名稱空間作用域中,或者對於成員函式和友元函式,出現在類作用域中。在類體中宣告且沒有 friend 說明符的函式是類成員函式。此類函式具有許多額外的特性,詳見成員函式。
函式不是物件:沒有函式陣列,函式不能按值傳遞或從其他函式返回。允許使用函式指標和引用(主函式和大多數標準庫函式除外(C++20 起)),並且可以在函式本身無法使用的地方使用它們。因此我們說這些函式是“可定址的”。
每個函式都有一種型別,由函式的返回型別、所有引數的型別(經過陣列到指標和函式到指標的轉換後,參見引數列表)、函式是否是noexcept
(C++17 起),以及對於非靜態成員函式,cv-限定和引用限定(C++11 起)組成。函式型別還具有語言連結。不存在 cv-限定函式型別(不要與cv-限定函式的型別混淆,例如int f() const;,或返回cv-限定型別的函式,例如std::string const f();)。如果將任何 cv-限定符新增到函式型別的別名中,則該限定符將被忽略。
同一作用域中的多個函式可以具有相同的名稱,只要它們的引數列表以及對於非靜態成員函式,cv/ref(C++11 起)-限定不同即可。這稱為函式過載。僅返回型別和 noexcept 規範(C++17 起)不同的函式宣告不能過載。過載函式的地址以不同的方式確定。
C++ 使用lambda 表示式實現匿名函式。 |
(C++11 起) |
[編輯] 函式物件
除了函式左值,函式呼叫表示式還支援函式指標以及過載函式呼叫運算子或可轉換為函式指標的任何類型別值(包括lambda 表示式)(C++11 起)。總的來說,這些型別被稱為函式物件(FunctionObject),它們在 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 起))。