1、 爲何要使用函數ios
1. 函數能夠重複使用,使用時能夠只關心函數的功能和使用方法而沒必要關心函數功能的具體實現,這樣有利於代碼重用;算法
2. 使用函數也能夠提升開發效率,便於分工合做;數組
eg:如今須要設計一個規模很大的程序,它有幾千項功能,把這些功能都編寫在一個主函數裏就只能由一我的來編寫,由於每一個人解決問題的思路是不一樣的,並且在主函數中的變量名是不能重複的,只有編寫者本身知道哪些變量名是可使用的。這樣一來,沒有一年半載,這個程序是沒法完成的。如果咱們把這幾千項功能分拆爲一些函數,分給幾百我的去編寫,那麼用不了幾天時間這些函數就都可以完成了。最後用主函數把這些完成的函數組織一下,一個程序很快就完工了。函數
3. 使用函數能夠增長程序的可讀性;spa
eg:如今要設計一個「學生信息處理程序」,須要完成四項工做,分別是記錄學生的基本狀況、學生成績統計、優秀學生狀況統計和信息輸出。若是咱們把四項工做全都寫在主函數裏面,那麼咱們就很難分清那一段代碼在作什麼。多層次的縮進和不能重複的變量名給咱們閱讀程序帶來了困難。若是咱們爲每個功能編寫一個函數,那麼根據函數名每一個函數的功能就很清晰了。若是咱們要修改某一個函數的功能,其餘的函數也絲絕不會受到影響。
設計
4. 使用函數能夠加強程序的可靠性,也便於修改和維護。指針
2、 爲何要用函數重載code
1. 函數重載:函數重載是函數的一種特殊狀況,C++中容許在同一做用域中聲明幾個功能相似的同名函數,這些同名函數的形參列表(包括參數個數,參數類型和參數順序)必須不一樣,經常使用來處理實現功能相似但數據類型不一樣的問題。簡單理解就是「一物多用」。對象
eg:blog
① 類型不一樣;
好比int類型的加法和float類型的加法函數,不用重載可能要這麼寫 int addInt(int a,int b); float addFloat(float a, float b); 調用時一樣要用不一樣的函數名調用。可是用了重載,就都只要用add函數名了,也不用操心傳進去的是int仍是 float類型的參數。
int add(int x,int y);
float add(double x, double y);
② 個數不一樣
int add(int x, int y);
int add(int x,int y,int z);
3、 什麼是值傳遞
1. 值傳遞:單向傳遞,形參只是獲得實參的值,它和實參是兩個不一樣的對象,不會互相影響,改變形參,不影響實參。
例:
#include<iostream> 2 using namespace std; 3 void Swap(int, int); 4 5 int main() 6 { 7 int a = 1, b = 2; 8 cout << "a的值爲:" << a << "b的值爲:" <<b<<endl; 9 Swap(a, b); 10 cout << "a的值爲:" << a << "b的值爲:" <<b<<endl; 11 } 12 13 void Swap(int x, int y) 14 { 15 int temp; 16 temp = x; 17 x = y; 18 y = temp; 19 cout << "Swap函數中a的值爲:" << x << "Swap函數中b的值爲:" << y << endl; 20 }
運行結果:
從上面能夠看出,主函數聲明瞭兩個全局變量a,b並對其賦值1,2;經過函數Swp()函數調用以後,在函數內部將a和b的值交換了,使得函數內,a=2,b=1;可是,這個過程並無改變全局變量a和b的值。
分析:
函數Swap()被調用前,實參a和b有本身的存儲空間,而且有本身的初始值。當調用函數Swap()時,爲形參(即函數的參數)x和y分配存儲空間,並將a和b的值複製過來,函數執行過程當中,將x和y的值進行交換,當函數執行結束以後,x和y所佔用的存儲空間將被釋放,這種傳遞的方式,並不會對實參a和b的值產生影響,此即爲值傳遞。
例2:在下列原型所示的C++函數中,按「傳值」方式傳遞參數的是( )
A. Void f1(int x); B.void f2(int *x); C.void f3(const int *x); D.void f4(int &x);
答案:A
解析:函數參數的3種傳遞方式:①將變量名做爲形參和實參,即傳值方式;②傳遞變量指針;③引用形參。其中B、C選項都是傳遞變量指針,D選項爲引用形參,因此本題答案爲A。
4、 什麼是地址傳遞
1. 地址傳遞:就是當調用一個過程時,是把實參變量的內存地址傳遞給被調用過程的形參,也就是說形參與實參使用相同地址的內存單元。所以當在被調用過程當中改變形參的值,就等於改變了實參的值。
例:
1 void Swap2(int *p, int *p) 2 { 3 int temp=*p; 4 *p=*p; 5 *p=temp; 6 print(「*p=%d, *p=%d\n」, *p, *p); 7 } 8 9 int main() 10 { 11 int a=2; 12 int b=7; 13 swap2(&a,&b); 14 Print(「a=%d, b=%d\n」, a, b); 15 }
輸出結果:
*p=7, *p=2
a=7, b=2
分析:
在這個程序中,指針變量做參數,在Swap2函數裏,隱含地存在p=&a; p=&b;這兩條語句,表示a的地址代入到了p,b的地址代入到了p。雖然傳送的是變量的地址,但實參和形參之間的數據傳遞仍然是單向的「值傳遞」,即調用函數不可能改變實參指針變量的值。但它不一樣於通常值傳遞的是,它能夠經過指針間接訪問的特色來改變指針變量所指變量的值,最終達到改變實參的目的。
5、 如何編寫遞歸函數
1. 什麼是遞歸
簡單的定義: 「當函數直接或者間接調用本身時,則發生了遞歸。」
例:經過遞歸來計算長度
1 size_t length(const char *str) 2 { 3 if (*str == 0) { 4 return 0; 5 } 6 return length(++str) + 1; 7 }
2. 使用遞歸
經典的例子就是斐波那契數列, 在數學上, 斐波那契數列就是用遞歸來定義的:
1 F0 = 0 2 F1 = 1 3 Fn = Fn – 1 + Fn – 2
注:
在編寫遞歸函數時要注意,函數中的局部變量和參數只是侷限於當前調用層,當遞推動入「簡單問題」層時,原來層次上的參數和局部變量便被隱蔽起來。在一系列「簡單問題」層,它們各有本身的參數和局部變量。
因爲遞歸引發一系列的函數調用,而且可能會有一系列的重複計算,遞歸算法的執行效率相對較低。當某個遞歸算法能較方便地轉換成遞推算法時,一般按遞推算法編寫程序。例如上例計算斐波那契數列的第n項的函數fib(n)應採用遞推算法,即從斐波那契數列的前兩項出發,逐次由前兩項計算出下一項,直至計算出要求的第n項。