復(fù)習(xí)函數(shù)的基本知識(shí)
要使用C++函數(shù),必須完成如下工作:
- 提供函數(shù)定義
- 提供函數(shù)原型
- 調(diào)用函數(shù)?
庫(kù)函數(shù)是已經(jīng)定義和編譯好的函數(shù),同時(shí)可以使用標(biāo)準(zhǔn)庫(kù)頭文件提供其原型,因此只需要正確地調(diào)用這種函數(shù)即可。但是創(chuàng)建自己的函數(shù)時(shí),必須自行處理上面提到的3個(gè)方面。例如
#include<iostream>
using namespace std;
void hello(); //函數(shù)的聲明
int main()
{
cout << "主函數(shù)將調(diào)用自己編寫(xiě)的hello這個(gè)函數(shù):" << endl;
hello(); //函數(shù)的調(diào)用
cout << "調(diào)用自編函數(shù)hello結(jié)束" << endl;
return 0;
}
//函數(shù)的聲明
void hello()
{
cout << "我向大家問(wèn)好!"<<endl;
}
?
程序按行順序執(zhí)行。執(zhí)行函數(shù)hello()時(shí),將暫停main()中的代碼;等函數(shù)hello()執(zhí)行完畢之后,繼續(xù)執(zhí)行main()中的代碼。?
定義函數(shù)
可以將函數(shù)分為兩類(lèi):沒(méi)有返回值的和有返回值的函數(shù)。
沒(méi)有返回值的函數(shù)稱(chēng)為void函數(shù),通用格式如下:
void functionName(parameterList)
{
statement(s)
return;
}
?其中,parameterList指定了傳遞給函數(shù)的參數(shù)類(lèi)型和數(shù)量。
有返回值的函數(shù)將生成一個(gè)值,并將它返回給調(diào)用函數(shù)。這種函數(shù)的返回類(lèi)型被聲明為返回值的類(lèi)型。通用格式如下:
typeName functionName(parameterList)
{
statement(s)
return value;
}
?對(duì)于有返回值的函數(shù),必須使用返回語(yǔ)句,以便將值返回給調(diào)用函數(shù)。注意返回值的類(lèi)型不能是數(shù)組,但可以是其他任何類(lèi)型——整數(shù)、浮點(diǎn)數(shù)、指針、結(jié)構(gòu)、對(duì)象
函數(shù)在執(zhí)行返回語(yǔ)句后結(jié)束。如果函數(shù)包含多條返回語(yǔ)句,則函數(shù)在執(zhí)行遇到的第一條返回語(yǔ)句后結(jié)束。例如
int bigger(int a,int b)
{
if(a > b)
return a;
else
return b;
}
?函數(shù)原型和函數(shù)調(diào)用
看下面一個(gè)例子
#include<iostream>
using namespace std;
void cheers(int); //prototype, no return value
double cube(double x); //prototype, return a double
int main()
{
cheers(5); //function call
cout << "Give me a number: ";
double side;
cin >> side;
double volume = cube(side); //function call
cout << "A " << side << "-foot cube has a volume of ";
cout << volume << " cubic feet" << endl;
cheers(cube(2));
return 0;
}
void cheers(int n)
{
for (int i = 0; i < n; i++)
{
cout << "Cheers! ";
}
cout << endl;
}
double cube(double x)
{
return x * x * x;
}
?
1.為什么需要原型?
原型描述了函數(shù)到編譯器的接口,也就是說(shuō)它將函數(shù)返回值的類(lèi)型(如果有的話)以及參數(shù)的類(lèi)型和參數(shù)的數(shù)量告訴編譯器。
函數(shù)原型是怎樣影響下面這條語(yǔ)句的??
double volume = cube(side);
?對(duì)于上面這條語(yǔ)句,函數(shù)原型告訴編譯器,cube()有一個(gè)double參數(shù)。如果程序沒(méi)有提供這樣的參數(shù),原型將讓編譯器能夠捕獲這種錯(cuò)誤;其次,cube()函數(shù)完成計(jì)算后,將把返回值放在指定的位置,然后調(diào)用函數(shù)(這里是main()函數(shù))將從這個(gè)指定位置取得返回值。由于原型指出了cube()的返回類(lèi)型是double,因此編譯器知道應(yīng)該檢索多少字節(jié)以及如何解釋它們。如果沒(méi)有這些信息,編譯器將只能進(jìn)行猜測(cè),而編譯器是不會(huì)這樣做的。
2.原型的語(yǔ)法
函數(shù)的原型是一條語(yǔ)句,因此必須以分號(hào)結(jié)束。最簡(jiǎn)單的方法就是 復(fù)制函數(shù)定義中的函數(shù)頭并添加分號(hào)。(函數(shù)原型不要求提供變量名,有類(lèi)型列表就行了;下面這兩種都是正確的)
void hell(int);
void hell(int x);
3.原型的功能
原型確保以下幾點(diǎn):
- 編譯器正確處理函數(shù)返回值
- 編譯器檢查使用的參數(shù)數(shù)目是否正確
- 編譯器檢查使用的參數(shù)類(lèi)型是否正確;如果不正確,則在能力范圍內(nèi)轉(zhuǎn)換為正確的類(lèi)型?
函數(shù)參數(shù)和按值傳遞?
?C++通常按值傳遞參數(shù),這意味著將數(shù)值參數(shù)傳遞給函數(shù),而后者將其賦給一個(gè)新的變量。
用于接收傳遞值的變量被稱(chēng)為形參,傳遞給函數(shù)的值被稱(chēng)為實(shí)參。
?在函數(shù)中聲名的變量(包括參數(shù))是該函數(shù)私有的。在函數(shù)被調(diào)用時(shí),計(jì)算機(jī)將為這些變量分配內(nèi)存,在函數(shù)結(jié)束時(shí),計(jì)算機(jī)將釋放這些變量使用的內(nèi)存,這樣的變量被稱(chēng)為局部變量。
如果在main()中聲明了一個(gè)名為x的變量,同時(shí)在另一個(gè)函數(shù)中也聲明了一個(gè)名為x的變量,則它們將是兩個(gè)完全不同的、毫無(wú)聯(lián)系的變量
多個(gè)參數(shù)
?函數(shù)可以有多個(gè)參數(shù),在調(diào)用函數(shù)時(shí),只需使用逗號(hào)將這些參數(shù)分開(kāi)即可:
n_chars('R',50);
?上述函數(shù)調(diào)用將兩個(gè)參數(shù)傳遞給函數(shù)n_chars()
同樣,在定義函數(shù)時(shí),也在函數(shù)頭中使用由逗號(hào)分隔的參數(shù)聲名列表
void n_chars(char c,int n) //two arguments
該函數(shù)頭指出,函數(shù)n_chars()接受一個(gè)char參數(shù)和一個(gè)int參數(shù),必須分別指定每個(gè)參數(shù)的類(lèi)型,不能像聲明常規(guī)變量那樣,將聲明組合在一起。
函數(shù)和數(shù)組
函數(shù)是處理復(fù)雜類(lèi)型(如數(shù)組、結(jié)構(gòu))的關(guān)鍵,下面學(xué)習(xí)如何將數(shù)組和函數(shù)結(jié)合在一起
假設(shè)現(xiàn)在要計(jì)算一個(gè)數(shù)組中所有元素的和,我們可以使用for循環(huán)逐個(gè)遍歷相加即可,這樣沒(méi)換一個(gè)數(shù)字都要進(jìn)行相應(yīng)的修改。這里我們寫(xiě)出一個(gè)統(tǒng)一的接口,讓對(duì)于不同的數(shù)組修改的盡可能少,不必每次都編寫(xiě)新的循環(huán)。
#include<iostream>
using namespace std;
const int ArSize = 8;
int sum_arr(int arr[], int n);
int main()
{
int cookies[ArSize] = { 1,2,4,8,16,32,64,128 };
int sum = sum_arr(cookies, ArSize);
cout << "Total cookies: " << sum << endl;
return 0;
}
int sum_arr(int arr[], int n)
{
int total = 0;
for (int i = 0; i < n; i++)
{
total = total + arr[i];
}
return total;
}
?
?我們看函數(shù)頭
int sum_arr(int arr[], int n)
?方括號(hào)指出arr是一個(gè)數(shù)組,方括號(hào)為空則表示可以將任何長(zhǎng)度的數(shù)組傳遞給該函數(shù)。但實(shí)際情況并不是這樣:arr實(shí)際上并不是數(shù)組,而是一個(gè)指針。(在編寫(xiě)函數(shù)的其余部分時(shí),可以將arr看作是數(shù)組)
函數(shù)如何使用指針來(lái)處理數(shù)組
前面介紹過(guò),C++將數(shù)組名解釋為其第一個(gè)元素的地址
cookies == &cookies[0]
?數(shù)組聲明使用數(shù)組名來(lái)標(biāo)記存儲(chǔ)位置,對(duì)數(shù)組名使用sizeof將得到整個(gè)數(shù)組的長(zhǎng)度(以字節(jié)為單位),將取地址運(yùn)算符&用于數(shù)組名時(shí),將返回整個(gè)數(shù)組的地址
在函數(shù)調(diào)用:
int sum = sum_arr(cookies, ArSize);
其中cookies是數(shù)組名,而根據(jù)C++規(guī)則,cookies是其第一個(gè)元素的地址,因此函數(shù)傳遞的是地址。由于數(shù)組的元素的類(lèi)型為int,因此cookies的類(lèi)型必須是int指針,即int*。這表明正確的函數(shù)頭應(yīng)該是這樣的:
int sum_arr(int *arr,int n)
這證明 int *arr和int arr[ ]這兩個(gè)函數(shù)頭都是正確的。因?yàn)樵贑++中,當(dāng)且僅當(dāng)用于函數(shù)頭或函數(shù)原型中,它們兩者的含義才是相同的,都意味著arr是一個(gè)int指針。在其他的上下文中,? ? ? ? ? ? ? ? ? ?int * arr和int arr[ ]的含義是不同的。?
?我們可以看到,上述程序并沒(méi)有將數(shù)組內(nèi)容傳遞給函數(shù),而是將數(shù)組的位置(地址)、包含的元素種類(lèi)(類(lèi)型)以及元素?cái)?shù)目(變量n)傳遞給函數(shù),有了這些信息后,函數(shù)便可以使用原來(lái)的數(shù)組。
傳遞常規(guī)變量時(shí),函數(shù)將使用該變量的拷貝;但傳遞數(shù)組時(shí),函數(shù)將使用原來(lái)的數(shù)組。
?將數(shù)組地址作為參數(shù)可以節(jié)省復(fù)制整個(gè)數(shù)組所需的時(shí)間和內(nèi)存。
指針和const
可以用兩種不同的方式將const關(guān)鍵字用于指針。
第一種方法是讓指針指向一個(gè)常量對(duì)象,這樣可以防止使用該指針來(lái)修改所指向的值;
int age = 39;
const int* pt = &age;
該聲明指出,pt指向一個(gè)const int(39),因此不能使用pt來(lái)修改這個(gè)值
*pt += 1; //INVALID
cin >> *pt; //INVALID
pt的聲明并不意味著它指向的值實(shí)際上就是一個(gè)常量,而只意味著對(duì)pt而言,這個(gè)值是常量。(例如pt指向age,而age不是const,可以直接通過(guò)age變量來(lái)修改age的值,但是不能使用pt指針來(lái)修改它)
*pt = 20; //INVALID
age = 20;
在這里注意又有兩種情況,以前我們總是將常規(guī)變量的地址賦給常規(guī)指針,而這里將常規(guī)變量的地址賦給指向const的指針(因此還有兩種情況:將const變量的地址賦給指向const的指針、將const變量的地址賦給常規(guī)指針。其實(shí)只有第一種可行,第二種是不可行的)
const float g_earth = 9.8;
const float *pe = &g_earth; //VALID
?對(duì)于這一種情況,既不能使用g_earth來(lái)修改值9.8,也不能使用指針pe來(lái)修改。
?盡可能使用const
將指針參數(shù)聲明為指向常量數(shù)據(jù)的指針有兩條理由:
1)這樣可以避免由于無(wú)意間修改數(shù)據(jù)而導(dǎo)致的編程錯(cuò)誤
2)使用const使得函數(shù)能夠處理const和非const實(shí)參,否則只能接受非const參數(shù)
第二種方法是將指針本身聲明為常量,這樣可以防止改變指針指向的位置。
int sloth = 3;
int *const finger = &sloth;
?這種聲明結(jié)構(gòu)使得finger只能指向sloth,但允許使用finger來(lái)修改sloth的值
遞歸
C++函數(shù)有一種有趣的特點(diǎn)——可以自己調(diào)用自己(與C語(yǔ)言不同的是,C++不允許main()調(diào)用自己),這種功能被稱(chēng)為遞歸。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-546812.html
?如果遞歸函數(shù)調(diào)用自己,則被調(diào)用的函數(shù)也將調(diào)用自己,這將無(wú)限循環(huán)下去,除非代碼中包含終止調(diào)用鏈的內(nèi)容。通常的方法將遞歸調(diào)用放在if語(yǔ)句中,如下面的一個(gè)遞歸函數(shù)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-546812.html
void recurs(argumentlist)
{
statements1
if(test)
recurs(arguments2)
statements2
}
到了這里,關(guān)于第七章——函數(shù)(C++的編程模塊)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!