1. 程式人生 > >C++基礎知識(五)--函數重載--缺省參數--內聯函數

C++基礎知識(五)--函數重載--缺省參數--內聯函數

即使 功能 ble 增加 應該 匹配 pre 不足 復制

一、函數重載--用相同的函數名定義一組功能相同或類似的函數,程序的可讀性增強

  1函數重載:在實際的開發中需要定義幾個功能類似而參數類型不同的函數那麽這樣的幾個函數可以使用相同的函數名,這就是函數的重載。簡言之就是一個函數名可以有多種用途。

  2.函數重載提高了程序的可讀性,函數參數列表的不同包括:參數的個數不同,類型不同,或順序不同,僅僅參數名稱不同是不可以的,函數的返回值也不能作為重載的依據。

  3.函數重載的規則:

  • 函數名稱必須相同
  • 參數列表必須不同(個數不同,類型不同,參數排列順序不同等)
  • 函數的返回類型可以相同也可以不同
  • 僅僅返回類型不同不足以成為函數重載的依據

  4.C++是如何實現函數重載的

      1.C++代碼在編譯的時候會根據參數列表進行重命名,例如void swap(int a,int b)會被重命名為_swap_int_int,,,void swap(float x,float y)會被重命名為_swap_float_float。當發生函數調用時,編譯器會根據傳入的實參去逐個匹配,以選擇對應的函數,如果匹配失敗,編譯器就會報錯,這叫做重載決議。

      2.函數的重載僅僅是語法上的不同,本質上還是不同的函數,占用的內存不同,函數的入口地址也不同。

1 int sum(int a,int b)
2 double sum(double a,double b)
3 float
sum(float a,float b,float c)




二、 C++函數缺省參數

  1.默認參數:在定義函數時為形參指定默認值(缺省值),這樣函數在調用時,對於默認參數可以給出實參值也可以不給出實參值。如果給出實參值,將實參傳遞給形參進行調用,如果不給出實參,則按默認值進行調用。

  2.默認參數的函數調用:默認實參並不一定是常量表達式,可以是任意表達式甚至可以通過函數調用給出,如果默認實參是任意表達式,則函數每次調用時該表達式被重新求值。但表達式必須有意義。

  3.默認的參數可以有多個,但所有默認參數必須放在參數表的右側,即先定義所有的非默認參數,再定義默認參數。這是因為在函數調用時,參數自左向右逐個匹配,當實參與形參個數不一致時只有這樣才不會產生二義性。

  4.在同一作用域內,一個參數只能被指定一次默認值,不可以在聲明和定義中同時指定默認值,即使默認值一樣也不行。習慣上,缺省參數在公共頭文件包含的函數聲明中指定,否則缺省函數只能用於包含該函數定義的文件中的函數調用。

  5.在調用具有默認參數的函數時,若某個實參默認,其右邊的所有實參都應該默認

int fun(int i1=1,int i2=2,int i3=3);
//調用函數
fun();//正確全為默認值
fun(3);//正確 i1=3,i2=2,i3=3
fun(3,,4);//正確i1=3,i2=4,i3=3
fun(2,3,4);//正確 i1=2,i2=3,i3=4
fun(,6,7);錯誤i1為默認,i2,i3都不是默認



三、C++內聯函數------------ --本質是節省時間消耗空間

  1.內聯函數的引入

  • 當程序執行函數調用時系統需要建立棧空間,保護現場,傳遞參數以及控制程序執行的轉移等等,這些工作需要系統時間和空間的開銷
  • 當函數功能簡單,使用頻率很高時為了提高效率,直接將函數的代碼嵌入到程序中,,這個辦法有缺點,一是相同代碼重復書寫,而是程序可讀性沒有使用函數好
  • 為了協調好效率與可讀性之間的矛盾,C++引入了內聯函數

  2.內聯函數的定義

    在函數聲明前加inline

    在函數定義前加inline

  3.內聯函數的調用

  • 內聯函數的調用機制與一般函數不同,編譯器在編譯過程中遇到inline時,為該函數內建一段代碼,然後在每次調用時直接將該代碼嵌入到調用函數中,從而將函數調用方式變為順序執行方式,這一過程成為內聯函數的的擴展或內聯。因為inline指示符對編譯器而言只是一個建議,編譯器也可以選擇忽略該建議。

  4.只有當函數只有10行甚至更少時才將其定義為內聯函數。內聯是以代碼膨脹(復制)為代價的,僅僅省去了函數調用的開銷,從而提高函數的執行效率。如果執行函數體內代碼的時間相比較於函數調用的的開銷較大,那麽效率就不明顯了,而且每一處內聯函數的調用都要復制代碼,使程序的總代碼量增加,消耗更多的內存空間。




  •   內聯函數的使用規則,inline函數何時不被展開
    • 含有遞歸調用的函數不能設置為內聯函數:因為程序無法在每次編譯時知道要遞歸的次數,所以不能進行代碼替換
    • 使用了循環語句與開關語句(switch)的函數不能設置為內聯函數
    • inline關鍵字只是對編譯器的一個建議,如果編譯器發現指定的函數不適合內聯就不會內聯
    • 內聯函數必須在調用之前聲明,關鍵字inline與函數定義體放在一起才能使函數成為內聯,僅將inline放在函數聲明前不起任何作用
    • 在一個函數體中定義的內聯函數不能再另一個文件中使用,他們通常放在頭文件中共享。
  • 定義在類聲明中的成員函數將自動成為內聯函數
    • 1 class A
      2 {
      3 public:
      4 void fun(int x,int y){}//定義在類聲明中,自動的成為內聯函數
      5 }

      將成員函數的定義放在類聲明之中雖然能帶來書寫上的方便,但不是良好的編程風格,上例應該改為

    •  1 //頭文件
       2 class A
       3 {
       4 public:
       5 void fun(int x,int y);
       6 }
       7 //定義頭文件
       8 inline void A::fun(int x,int y)
       9 {
      10 
      11 }

  類的構造函數與析構函數容易讓人誤以為內斂更有效,但應該註意構造函數與析構函數中可能隱藏的一些行為,如偷偷地執行了基類或成員對象的構造函數與析構函數。所以不要將構造函數與析構函數的定義放在類聲明中。一個好的編譯器會根據函數的定義題,自動的取消不值得的內聯。

C++基礎知識(五)--函數重載--缺省參數--內聯函數