C++語言程式設計基礎課程筆記03
本文將介紹 C++ 中 函式的一般用法。函式又稱為方法,是一段程式程式碼。由三部分組成,函式宣告,函式定義 和 函式體。
- 函式定義包含函式返回值,函式名 和 形式引數(形參)列表
- 函式體中是一些語句。
- 函式宣告, 寫法和函式定義差不多,但是沒有函式體。通常可以預設,但是如果被呼叫,但函式定義還沒有出現,需要在呼叫之前書寫函式宣告
例如:
// 函式宣告
int add(int a, int b);
// 返回值, 函式名, 形參列表
int add(int a, int b) {
// 函式體
return a + b;
}
呼叫是可以被呼叫的, 呼叫時需要提供實際引數(實參)列表。
這裡常量“cpp” 就是實參, name 就是形參
#include <iostream>
#include <string>
using namespace std;
int hi(string name) {
cout << "hi" << name << endl;
}
int main() {
cout << "1" << endl;
hi("cpp");
cout << "2" << endl;
}
語句按照順序執行,遇到函式先執行函式內部,返回之後繼續執行。
和大多數程式一樣,函式可以巢狀,函式中又可以呼叫其他的函式。
而函式呼叫自身,稱為遞迴,編寫演算法的時候經常使用遞迴。
unsigned fib(unsigned int n) {
if (n == 1) {
return 1;
}
if (n == 2) {
return 1;
}
return fib(n - 2) + fib(n - 1);
}
通常遞迴需要退出條件。
下面介紹一些要點 和特性, 實參形參和引用、constexpr、預設引數、函式過載
關於形參和實參,實參就是呼叫的時候填寫的引數,當執行呼叫的時候,會發生實形結合。實形結合,就是形參會被分配記憶體空間,並且實參的值會傳遞給形參。定義的時候形參不佔用記憶體空間。
引數傳遞有兩種:
-
單項傳遞,也就是傳值,這樣函式內如果需要改變實參,就不行的,因為不在一個記憶體空間。那麼需要通過雙向傳遞來實現,
-
雙向傳遞,就是傳引用,需要把形參的型別設定為引用型別,那麼實形結合的時候,會把形參的引用和實參的資料繫結,這個繫結關係不會改變,並且形參不佔用記憶體空間。
引用 不是變數,是變數的別名,不佔用記憶體空間,寫法如下:
# 型別& 是一個引用型別
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
int main() {
int x = 1;
int y = 2;
swap(x, y);
cout << "x = " << x << ",y = " << y << endl;
}
那麼 a 是一個引用型別 和 實參x的資料進行繫結,是x 的別名,通過雙向傳遞,可以改變實參的值。
constexpr 是 c++ 中的一個關鍵字,可以新增到函式的定義或者宣告開頭,這個語法是一個比 const 更嚴格的語法
- 要求函式體的所有引數是 constexpr 時,返回值也是 constexpr
- 函式中只能有return語句
有什麼用呢,總結來說,就是 constexp r要求編譯時不可變(而 const 只是執行時不可變,編譯時有可能值還沒有確定,還是變數),即在編譯時可以推匯出來,這樣嚴格約束,一方面描述這是一個常量表達式, 另外一方面可以在編譯時進行優化。
預設引數,這個在python中是支援的,C++ 的寫法類似,允許設定預設的引數,這樣在呼叫時可以不提供某些實參,但是預設引數需要從右到左提供,不用都提供。例如:
int test1(int a , int b = 1, int c = 2); // ok
int test2(int a = 1, int b ) // error
如果函式宣告中已經寫了預設引數,函式定義中就不用寫預設引數了。
函式過載(overload),是指一個相同名稱的函式,通過引數數量和引數型別的不同,有多個版本的功能。例如:
int add(int a , int b);
double add(double a, double b);
需要注意的,過載是不支援返回值型別不同的。(因為隱式型別轉換的存在,可能引起歧義)。雖然說好處的是可以用同一個方法名,反覆使用,而不用使用addInt addDouble這樣的名稱。對於使用函式的人來說,需要注意的是,由於使用的引數不同,需要確定實際上是呼叫哪個方法。
總之,函式是程式設計中隨處可見的操作,C++ 需要注意的就是引數傳遞和函式宣告。