在面向對象的程序設計中,函數是面向對象程序設計中對功能的抽象算法
Q:函數這麼重要,爲何要使用函數呢?函數
A:一個較爲複雜的系統每每須要劃分爲若干個系統,而後對這些子系統分別進行開發調試。C與C++語言則體現爲函數。函數編好後,能夠被重複使用,使用時能夠只關心函數的功能和使用辦法而沒必要關係函數功能的具體實現,這樣有利於代碼的重用,能夠提升代碼效率,加強程序的可靠性,也便於分工合做和修改。spa
函數的定義:設計
類型說明賦 函數名(含類型說明的形式參數表) { 語句序列 }
形式參數(簡稱形參)表的內容以下:3d
type 1 name1,type 2 name 2,…調試
其中name n是形參名。形參的做用是實現主調函數與被調函數之間的關係。code
兩個以上的函數,具備相同的函數名,可是形參的個數或者類型不一樣,編譯器根據實參和形參的類型及個數的最佳匹配,自動肯定調用哪個函數,這就是函數的重載。對象
Q:爲何要用這個功能呢?blog
A:若是沒有重載機制,那麼對不一樣類型的數據進行相同的操做也須要定義名稱徹底不一樣的函數。實是麻煩。
eg:
int add(int x,int y); float add(float x,float y); //與上式形參類型不一樣 int add(int x,int y); int add(int x,int y,int z); //與上式形參個數不一樣
注意&習慣:不要將不一樣功能的函數定義爲重載函數,以避免出現對調用結果的誤解、混淆。
值傳遞是指當發生函數調用時,給形參分配內存空間,並用實參來初始化形參(直接將實參的值傳給形參)。這一過程時參數值的單向傳遞過程,一旦形參得到了值便於實參脫離關係,此後不管形參發生了怎麼樣的改變,都不會影響到實參。
Q:舉個栗子吧!
A:舉一個經典的例子!交換整數!
#include <iostream> using namespace std; void swap(int a,int b){ int t = a; a = b; b = t; } int main(){ int x=5,y=10; cout<<"x="<<x<<" y="<<y<<endl; swap(x,y); cout<<"x="<<x<<" y="<<y<<endl; return 0; }
分析:因爲採用的是值傳遞,函數調用時傳遞的是實參的值,是單向傳遞過程,形參的改變對實參不起做用。
引用是一種特殊類型的變量,能夠被認爲是另外一個別名,經過引用名與經過被引用的變量名訪問變量的效果是同樣的。
使用引用時必須注意下列問題。
1)聲明一個引用時,必須對它進行初始化,使它指向一個已存在的對象。
2)一旦一個引用被初始化後,就不能改成指向其餘對象。
Q:和值傳遞有什麼區別呢?
A:咱們用代碼來證實!
#include <iostream> #include <iomanip> using namespace std; void fiddle(int in1,int &in2){ in1=in1+100; in2=in2+100; cout<<"The values are"; cout<<setw(5)<<in1; cout<<setw(5)<<in2<<endl; } int main(){ int v1=7,v2=12; cout<<"The values are"; cout<<setw(5)<<v1; cout<<setw(5)<<v2<<endl; fiddle(v1, v2); cout<<"The values are"; cout<<setw(5)<<v1; cout<<setw(5)<<v2<<endl; return 0; }
分析:子函數fiddle的第一個參數in1時普通的int型,被調用時傳遞的是實參v1的值,第二個參數in2是引用,被調用時由實參v2初始化稱爲v2的一個別名。因而在子函數中對參數in1的改變不影響實參,而對形參in2的改變實際上就是對住函數中變量v2的改變。於是返回主函數後,v1值沒有改變,而v2值發生了改變。
函數能夠直接或間接地調用自身,稱爲遞歸調用。
所謂直接調用自身,就是真在一個函數的函數體中出現了對自身的調用表達式。
eg:
void fun1(){ … fun1(); //調用函數自身 }
遞歸算法的實質是將原有的問題分解爲新的問題,二解決新的問題又用到了原有問題的解法。按照這一原則分解下去,每次出現的新問題都是原有問題的簡化的子集,而最終分解出來的問題,是一個已知解的問題。這即是有限的遞歸調用。只有有限的遞歸調用纔是有意義的。
遞歸的過程有以下兩個階段:
1)遞推
將原有問題不斷分解爲新的問題,逐漸從未知向已知推動,最終達到已知的條件,即遞歸結束的條件,這時遞歸階段結束。
2)迴歸
從已知的條件出發,按照遞推的逆過程,逐一求值迴歸,最後大道遞推的開始處,結束迴歸的階段,完成遞歸階段。
Q:用遞歸知識解決漢諾塔問題。
A:ok👌
分析:將n個盤子從A針移到C針能夠分解爲下面3個步驟
1.將n個盤子從A針移到B針上(藉助C針)
2.把A針上剩下的一個盤子移到C針上
3.將n-1個盤子從B針移到C針上(藉助A針)
上面三個步驟包含了兩個操做:
1.將多個盤子從一個針移到另外一個針上,這是一個遞歸的過程
2.將1個盤子從一個針上移到另外一個針上
用hanoi函數實現操做1,用move函數實現操做2
代碼以下:
#include <iostream> using namespace std; //src針的最上面一個盤子移動到dest針上 void move(char src,char dest){ cout<<src<<"-->"<<dest<<endl; } //把n個盤子從src針移動到dest針,以medium針做爲中介 void hanoi(int n,char src,char medium,char dest){ if (n==1) move(src,dest); else{ hanoi(n-1,src,dest,medium); move(src,dest); hanoi(n-1,medium,src,dest); } } int main(){ int m; cout<<"Enter the number of diskes:"; cin>>m; cout<<"the steps to moving"<<m<<" diskes:"<<endl; hanoi(m, 'A', 'B', 'c'); return