通過使用函數(functions)我們可以把我們的程序以更模塊化的形式組織起來,從而利用C++所能提供的所有結構化編程的潛力。
一個函數(function)是一個可以從程序其它地方調用執行的語句塊。以下是它的格式:
type name ( argument1, argument2, ...) statement |
這裏:
- type 是函數返回的數據的類型
- name 是函數被調用時使用的名
- argument 是函數調用需要傳入的參量(可以聲明任意多個參量)。每個參量(argument)由一個數據類型後面跟一個標識名稱組成,就像變量聲明中一樣(例如,int x)。參量僅在函數範圍內有效,可以和函數中的其它變量一樣使用, 它們使得函數在被調用時可以傳入參數,不同的參數用逗號(comma)隔開.
- statement 是函數的內容。它可以是一句指令,也可以是一組指令組成的語句塊。如果是一組指令,則語句塊必須用花括號{}括起來,這也是我們最常見到情況。其實爲了使程序的格式更加統一清晰,建議在僅有一條指令的時候也使用花括號,這是一個良好的編程習慣。
下面看一下第一個函數的例子:
// function example #include <iostream.h> int addition (int a, int b) { int r; r=a+b; return (r); } int main () { int z; z = addition (5,3); cout << "The result is " << z; return 0; } |
The result is 8 |
記得在我們教程開始時說過:一個C++程序總是從main函數開始執行。 因此我們從那裏開始。
我們可以看到 main 函數以定義一個整型變量z 開始。緊跟着我們看到調用addition 函數。我們可以看到函數調用的寫法和上面函數定義本身十分相似:
參數有明顯的對應關係。在main 函數中我們調用addition 函數,並傳入兩個數值: 5 和3 , 它們對應函數addition 中定義的參數int a 和int b。
當函數在main 中被調用時,程序執行的控制權從main轉移到函數addition。調用傳遞的兩個參數的數值 (5 和3) 被複制到函數的本地變量(local variables) int a 和int b 中。
函數addition 中定義了新的變量(int r;),通過表達式r=a+b;, 它把a 加b 的結果賦給r 。因爲傳過來的參數a 和b 的值分別爲5 和3 ,所以結果是8。
下面一行代碼:
return (r);
結束函數addition,並把控制權交還給調用它的函數(main) ,從調用addition的地方開始繼續向下執行。另外,return 在調用的時候後面跟着變量r (return (r);), 它當時的值爲8, 這個值被稱爲函數的返回值。
函數返回的數值就是函數的計算結果,因此, z 將存儲函數addition (5, 3)返回的數值, 即8。用另一種方式解釋,你也可以想象成調用函數(addition (5,3)) 被替換成了它的返回值 (8)。
接下來main中的下一行代碼是:
cout << "The result is " << z;
它把結果打印在屏幕上。
變量的範圍(Scope of variables) 你必須考慮到變量的範圍只是在定義該變量的函數或指令塊內有效,而不能在它的函數或指令塊之外使用。 例如,在上面的例子裏就不可能在main 中直接使用變量a, b 或 r ,因爲它們是函數addition的本地變量(local variable)。在函數addition中也不可能直接使用變量z,因爲它是main的本地變量。 因此,本地變量 (local variables)的範圍是侷限於聲明它的嵌套範圍之內的。儘管如此,你還可以定義全局變量(global variables),它們可以在代碼的任何位置被訪問,不管在函數以內還是以外。要定義全局變量,你必須在所有函數或代碼塊之外定義它們,也就是說,直接在程序體中聲明它們。 |
這裏是另一個關於函數的例子:
// function example #include <iostream.h> int subtraction (int a, int b) { int r; r=a-b; return (r); } int main () { int x=5, y=3, z; z = subtraction (7,2); cout << "The first result is " << z << '\n'; cout << "The second result is " << subtraction (7,2) << '\n'; cout << "The third result is " << subtraction (x,y) << '\n'; z= 4 + subtraction (x,y); cout << "The fourth result is " << z << '\n'; return 0; } |
The first result is 5 The second result is 5 The third result is 2 The fourth result is 6 |
在這個例子中,我們定義了函數subtraction。這個函數的功能是計算傳入的兩個參數的差值並將結果返回。
在 main 函數中,函數subtraction被調用了多次。我們用了幾種不同的調用方法,因此你可以看到在不同的情況下函數如何被調用。
爲了更好的理解這些例子,你需要考慮到被調用的函數其實完全可以由它所返回的值來代替。例如在上面例子中第一種情況下 (這種調用你應該已經知道了,因爲我們在前面的例子中已經用過這種形式的調用):
cout << "The first result is " << z;
如果我們把函數調用用它的結果(也就是5)替換,我們將得到:
cout << "The first result is " << z;
同樣的
cout << "The second result is " << subtraction (7,2);
與前面的調用有同樣的結果,但在這裏我們把對函數subtraction 的調用直接用作cout的參數。這可以簡單想象成我們寫的是:
cout << "The second result is " << 5;
因爲5 是subtraction (7,2)的結果。
在
cout << "The third result is " << subtraction (x,y);
中,與前面的調用唯一的不同之處是這裏調用subtraction 時的參數使用的是變量而不是常量。這樣用時毫無問題的。在這個例子裏,傳入函數subtraction 的參數值是變量x 和y中存儲的數值,即分別爲5 和3,結果爲2。
第四種調用也是一樣的。只要知道除了
z = 4 + subtraction (x,y);
我們也可以寫成:
z = subtraction (x,y) + 4;
它們的結果是完全一樣的。注意在整個表達式的結尾寫上分號semicolon sign (;)。它並不需要總是跟在函數調用的後面,因爲你可以有一次把它們想象成函數被它的結果所替代:
z = 4 + 2;
z = 2 + 4;
沒有返回值類型的函數,使用void.
如果你記得函數聲明的格式:
type name ( argument1, argument2 ...) statement
就會知道函數聲明必須以一個數據類型(type)開頭,它是函數由return 語句所返回數據類型。但是如果我們並不打算返回任何數據那該怎麼辦呢?
假設我們要寫一個函數,它的功能是打印在屏幕上打印一些信息。我們不需要它返回任何值,而且我們也不需要它接受任何參數。C語言爲這些情況設計了void 類型。讓我們看一下下面的例子:
// void 函數示例 #include <iostream> using namespace std; void printmessage () { cout << "I'm a function!"; } int main () { printmessage (); return 0; } |
I'm a function! |
void還可以被用在函數參數位置,表示我們明確希望這個函數在被調用時不需要任何參數。例如上面的函數printmessage也可以寫爲以下形式:
void printmessage (void) { cout << "I'm a function!"; }
雖然在C++ 中void可以被省略,我們還是建議寫出void,以便明確指出函數不需要參數。
你必須時刻知道的是調用一個函數時要寫出它的名字並把參數寫在後面的括號內。但如果函數不需要參數,後面的括號並不能省略。因此調用函數 printmessage 的格式是
函數名稱後面的括號就明確表示了它是一個函數調用,而不是一個變量名稱或其它什麼語句。以下調用函數的方式就不對: