C++中函數應用的根本常識進修教程。本站提示廣大學習愛好者:(C++中函數應用的根本常識進修教程)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中函數應用的根本常識進修教程正文
函數是履行某種操作的代碼塊。函數可以選擇性地界說使挪用方可以將實參傳遞到函數中的輸出形參。函數可以選擇性地前往值作為輸入。函數可用於在單個可重用塊中封裝經常使用操作(幻想情形是應用可清楚地描寫函數行動的稱號)。以下函數從挪用方接收兩個整數並前往其總和;a 和 b 是 int 類型的參數。
int sum(int a, int b) { return a + b; }
可以從法式中隨意率性數目的地位挪用函數。傳遞給函數的值是實參,其類型必需與函數界說中的形參類型兼容。
int main() { int i = sum(10, 32); int j = sum(i, 66); cout << "The value of j is" << j << endl; // 108 }
關於函數長度沒有現實限制,不外優越的設計應以履行單個明白界說的義務的函數為目的。龐雜算法應盡量分化成易於懂得的更簡略函數。
在類規模中界說的函數稱為成員函數。在 C++ 中(與其他說話分歧),函數還可以在定名空間規模中界說(包含隱式全局定名空間)。這類函數稱為 free 函數或非成員函數;它們在尺度庫中普遍應用。
函數聲明的各個部門
最小函數聲明包括前往類型、函數名和參數列表(能夠為空),和向編譯器供給附加解釋的可選症結字。函數界說包括聲明和函數體(這是年夜括號之間的一切代碼)。後接分號的函數聲明可以湧現在法式中的多個地位處。它必需在每一個翻譯單位中對該函數的任何挪用之前湧現。依據單個界說規矩 (ODR),函數界說必需僅在法式中湧現一次。
函數聲明的必須部門有:
前往類型,指定函數將前往的值的類型,假如不前往任何值,則為 void。在 C++11 中,auto 是有用前往類型,可指導編譯器從前往語句揣摸類型。在 C++14 中,還許可應用 decltype(auto)。有關具體信息,請參閱上面的“前往類型中的類型推導”。
函數名,必需以字母或下劃線開首,不克不及包括空格。普通而言,尺度庫函數名中的前導下劃線指導公有成員函數,或不是供你的代碼應用的非成員函數。
參數列表(一組用年夜括號限制、逗號分隔的零個或多個參數),指定類型和可以用於在函數體內拜訪值的可選部分變量名。
函數聲明的可選部門有:
constexpr,指導函數的前往值是常量值,可以在編譯時停止盤算。
constexpr float exp(float x, int n) { return n == 0 ? 1 : n % 2 == 0 ? exp(x * x, n / 2) : exp(x * x, (n - 1) / 2) * x; };
其 linkage 標准(extern 或 static)。
Declare printf with C linkage. extern "C" int printf( const char *fmt, ... );
inline,指導編譯器將對函數的每一個挪用調換為函數代碼自己。在某個函數疾速履行而且在機能症結代碼段中反復挪用的情形下,內聯可以贊助進步機能。
inline double Account::GetBalance() { return balance; }
noexcept,指定函數能否可以激發異常。鄙人面的示例中,函數在 is_pod 表達式盤算成果為 true 時不激發異常。
#include <type_traits> template <typename T> T copy_object(T& obj) noexcept(std::is_pod<T>) {...}
僅限成員函數)cv 限制符,指定函數是 const 照樣 volatile。
(僅限成員函數)virtual、override 或 final。 virtual 指定可以在派生類中重寫函數。 override 表現派生類中的函數在重寫虛函數。 final 表現函數不克不及在任何進一步的派生類中停止重寫。
(僅限成員函數僅)運用於成員函數的 static 表現函數不與類的任何對象實例聯系關系。
(僅限非靜態成員函數)ref 限制符,向編譯器指定隱式對象參數 (*this) 是右值援用與左值援用時要選擇的函數重載。
下圖顯示了函數界說的各個部門。灰色區域是函數體。
函數界說部門
函數界說
函數體內聲明的變量稱為部分變量。它們會在函數加入時超越規模;是以,函數應永久不前往對部分變量的援用!
函數模板
函數模板相似於類模板;它基於模板參數生成詳細功效。在很多情形下,模板可以或許揣摸類型參數,是以無需顯式指定它們。
template<typename Lhs, typename Rhs> auto Add2(const Lhs& lhs, const Rhs& rhs) { return lhs + rhs; } auto a = Add2(3.13, 2.895); // a is a double auto b = Add2(string{ "Hello" }, string{ " World" }); // b is a std::string 有關具體信息,請參閱函數模板
函數形參和實參
函數具有零種或多品種型的逗號分隔參數列表,個中每一個參數都具有可以用於在函數體內拜訪它的稱號。函數模板可以指定其他類型或值參數。挪用方傳遞實參(其類型與形參列表兼容的詳細值)。
默許情形下,參數經由過程值傳遞給函數,這意味著函數會收到所傳遞的對象的正本。關於年夜型對象,創立正本能夠本錢昂揚,並不是一直需要。若要使實參經由過程援用(特殊是左值援用)停止傳遞,請向形參添加援用限制符:
void DoSomething(std::string& input){...}
當函數修正經由過程援用傳遞的參數時,它會修正原始對象,而不是當地正本。若要避免函數修正這類實參,請將形參限制為
const&: void DoSomething(const std::string& input){...}
C++ 11:若要顯式處置經由過程右值援用或經由過程左值援用傳遞的實參,請對形參應用雙與號以指導通用援用:
void DoSomething(const std::string&& input){...}
只需症結字 void 是實參聲明列表中的第一個也是獨一一個成員,那末在形參聲明列表中應用單個症結字 void 聲明的函數就沒有實參。列表中的其他處所的 void 類型的參數發生毛病。例如:
// OK same as GetTickCount() long GetTickCount( void );
請留意,雖然指定 void 參數長短法(此地方述的除外),但派生自類型 void 的類型(如指向 void 的指針和 void 的數組)可以湧現在參數聲明列表中的任何地位。
默許參數
函數簽名中的最初一個或幾個形參能夠會分派有默許實參,這意味著挪用方能夠會在挪用函數時省略實參(除非要指定某個其他值)。
int DoSomething(int num, string str, Allocator& alloc = defaultAllocator) { ... } // OK both parameters are at end int DoSomethingElse(int num, string str = string{ "Working" }, Allocator& alloc = defaultAllocator) { ... } // C2548: 'DoMore': missing default parameter for parameter 2 int DoMore(int num = 5, // Not a trailing parameter! string str, Allocator& = defaultAllocator) {...}
函數前往類型
函數能夠不會前往另外一個函數或內置數組;然則,它可以前往指向這些類型的指針,或生成函數對象的 lambda。除這些情形,函數可以前往處於規模內的任何類型的值,或許它可以前往任何值(在這類情形下前往類型是 void)。
開頭前往類型
“通俗”前往類型位於函數簽名左邊。開頭前往類型位於簽名的最右邊,後面帶有 -> 運算符。當前往值的類型取決於模板參數時,開頭前往類型在函數模板中特別有效。
template<typename Lhs, typename Rhs> auto Add(const Lhs& lhs, const Rhs& rhs) -> decltype(lhs + rhs) { return lhs + rhs; }
當 auto 與開頭前往類型聯合應用時,它關於 decltype 表達式生成的任何內容都只用作占位符,自己不履行類型推導。
前往類型中的類型推導 (C++14)
在 C++14 中,可使用 auto 指導編譯器從函數體揣摸前往類型,而不用供給開頭前往類型。請留意,auto 一直推導為按值前往。應用 auto&& 可指導編譯器推扶引用。
在此示例中,auto 會推導為 lhs 和 rhs 之和的異常量值正本。
template<typename Lhs, typename Rhs> auto Add2(const Lhs& lhs, const Rhs& rhs) { return lhs + rhs; //returns a non-const object by value }
請留意,auto 不會保存它推導的類型的常量性。關於前往值須要保存其參數的常量性或援用性的轉發函數,可使用 decltype(auto) 症結字,該症結字應用 decltype 類型揣摸規矩並保存一切類型信息。 decltype(auto) 可以用作左邊的通俗前往值,或開頭前往值。
上面的示例(基於來自 N3493 的代碼)演示的 decltype(auto) 用於采取在模板實例化之前未知的前往類型完成函數參數的完善轉發。
template<typename F, typename Tuple = tuple<T...>, int... I> decltype(auto) apply_(F&& f, Tuple&& args, index_sequence<I...>) { return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...); } template<typename F, typename Tuple = tuple<T...>, typename Indices = make_index_sequence<tuple_size<Tuple>::value >> decltype( auto) apply(F&& f, Tuple&& args) { return apply_(std::forward<F>(f), std::forward<Tuple>(args), Indices()); } }
函數部分變量
在函數主體內聲明的變量稱為部分變量。非靜態部分變量僅在函數體中可見,假如它們在客棧上聲明,則會在函數加入時超越規模。結構部分變量並經由過程值前往它時,編譯器平日可以履行前往值優化以免不用要的復制操作。假如經由過程援用前往部分變量,則編譯器會收回正告,由於挪用方為應用該援用而停止的任未嘗試會在部分變量已燒毀以後停止。
部分靜態對象將在 atexit 指定的終止時代燒毀。假如某個靜態對象因為法式的掌握流跳過了其聲明而未結構,則不會測驗考試燒毀該對象。
靜態部分變量
在 C++ 中,部分變量可以聲明為靜態。變量僅在函數體中可見,然則關於函數的一切實例,存在變量的單個正本。
函數指針
C++ 經由過程與 C 說話雷同的方法支撐函數指針。然則加倍類型平安的替換辦法平日是應用函數對象。
建議應用 typedef 聲明函數指針類型的別號(假如聲明前往函數指針類型的函數)。例如
typedef int (*fp)(int); fp myFunction(char* s); // function returning function pointer
假如不履行此操作,則函數聲明的准確語法可以經由過程用函數稱號和參數列表調換標識符(上例中為 fp)來從函數指針的聲明符語法推導出,以下所示:
int (*myFunction(char* s))(int);
後面的聲明與應用下面的 typedef 的聲明等效。