第七章 函數(1)

C++創建使用一個函數必須完成三個工作:

提供函數原型 

提供函數定義

調用函數


首先講函數定義的通用格式:

typeName functionName(parameterList)

{

statements

return value

}

如果這個函數沒有返回值的話,typeName就是void,return value這一行也可以省略。C++的函數可以返回任何類型:整數,浮點數,指針,結構或者對象,但就是不能返回數組。

paramentList指定了傳遞給函數的參數類型和數量,具體稍後會介紹。


函數原型通常寫在頭文件中,原型是什麼呢?原型就是函數到編譯器的接口:它將函數返回值的類型(如果有的話)以及參數的類型和數量告訴編譯器。

函數原型是一條語句,必須以分號結束。獲取原型最簡單的方法是複製函數定義的第一行,並添加分號,比如我們有一個行數

double cube (double x) 

{ return x*x*x;}

函數原型可以寫爲

double cube(double x);

也可以省略變量名,直接寫成

double cube(double);


原型的功能就是確保以下幾點:

編譯器正確處理函數返回值;

編譯器檢查使用的參數數目是否正確;

編譯器檢查使用的參數類型是否正確,如果不正確,則轉爲正確的類型(如int轉成double)


下面介紹函數參數,還是看上面的cube函數,main中我們這樣調用:

double side = 12.3;

double volume = cube(side);

這樣調用cube函數時,該函數會創建一個新的名爲x的變量,並將side的值(12.3) 賦給x,然後對x進行計算。這樣就不會對side造成任何影響。

用於接收傳遞值得變量(x)被稱爲形參,傳遞給函數的值被稱爲實參。

那麼如果main中也有個x變量怎麼辦呢?答案是main裏面的x和cube裏面的x沒有任何關係,cube裏面的x被稱爲局部變量,只爲cube函數存在,所以cube函數一調用完,cube裏面的x就會被釋放。這樣的變量也叫做自動變量,因爲他們是在程序執行過程中自動被分配和釋放的。


函數可以有多個不同類型的參數,具體操作和單個參數一樣,函數定義和原型聲明的時候用逗號隔開。


前面說了函數的參數和返回值不能是數組,但現實中我們需要很多對數組的操作,怎麼辦呢?先講怎麼把數組作爲參數傳遞給函數:

其實看完這章之後我們可以完全把數組放在函數的參數裏面:

int sum_arr(int arr[], int n);

這完全合法!但這個時候c++不當arr是數組,而把它看成一個指針!但在編寫函數的其餘部分是,程序員可以將arr看成數組。(有點暈啊~~)。程序清單7.5很好的證明了這個用法。

其實c++把數組名視爲指針,比如我們有一個數組

int cookies[10];

這個數組的數組名cookies其實就是這個數組第一個元素的地址:

cookies = &cookies[0]

所以在sum_arr函數中我們傳遞的是這個數組第一個元素的地址(這個是可以有的)。因爲cookies是int的數組,所以數組名cookies的類型實際上是一個int指針int *,而這個函數的正確寫法應該是

int sum_arr(int *arr, int n).


注意的是:在C++中,當且僅當用於函數頭或者函數原型中int *arr和int arr[] 的含義才相同。


讀到這裏我們明白函數並沒有將數組內容傳遞給函數,而只是將數組的位置,包含的元素種類傳遞給函數。這樣好處就是避免傳遞數據量很大的數組,但風險就是現在可以對數組中的任何一個元素進行操作。如果要避免這種操作,就必須在函數頭和原型中在數組參數前面加const限定符:

int sum_arr(const int arr[], int n]);

還需要注意的是,這裏要使用arr[]數組作爲參數,我們一般還得把數組的長度傳給函數(上例中的int n),另外一個做法就是使用數組區間,把需要使用的數組區間的第一個元素和最後一個元素傳給函數(這裏他們都被看成指針)


const用於指針也比較微妙,可以用兩種不同的方式將const關鍵字用於指針:

讓指針指向一個常量對象,這樣可以防止使用該指針來修改所指向的值;

指針本身聲明爲常量,這樣可以防止改變指針指向的位置

比如:

int a = 10;

const int *pa = &a;

*pa = 20; //可以,因爲pa指向的a不是const

*pa +=1; //不可以,pa指向的地址不能改變


另外可以將const變量的地址賦給指向const的指針,但不能將const的地址賦給常規指針

比如

const int a = 10;

int *pa = &a; //這樣就是非法的了,pa* 也必須是const: const int *pa = &a;

到這裏就有點暈了,更暈的是const和可以這樣放

int * const pa = &a. 什麼區別呢,把書上的例子搬過來先吧:

int a = 1;

int b = 2;

const int *p1 = &a;

*p1 = 20; //不可以,因爲*p禁止修改它所指向的值

p1 = &b;// 可以,*p可以指向另一個地址


int *const p2 = &a;

*p2 = 20; // 可以

p2 = &b; // 不可以

但願讀者這個時候能看出區別了把:

const放最前面,表示(int *p1) 不能改,即p1指向的地址的值

const放中間表示(p2)不能修改,即p2指向的地址


如果數組是二維的,那麼放進去函數參數列表的數組名錶示二維數組的第一行第一個元素的地址 - 這個指針指向包含n(n等於二維數組的列數)元素的數組。


另外C風格字符串本身也是一個數組,將字符串作爲參數時就意味着傳遞的是第一個字符的地址。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章