天天看點

函數重載

出現在相同作用域中的兩個函數,如果具有相同的名字而形參表不同,則稱為重載函數。

可以定義一組函數,它們執行同樣的一般性動作,但是應用在不同的形參類型上,調用這些函數時,無需擔心調用的是哪個函數。

通過省去為函數起名并記住函數名字的麻煩,函數重載簡化了程式的實作,使程式更容易了解。

任何程式都僅有一個 main 函數的執行個體。main 函數不能重載。

函數重載和重複聲明的差別

如果兩個函數聲明的傳回類型和形參表完全比對, 則将第二個函數聲明視為第一個的重複聲明。如果兩個函數的形參表完全相同,但傳回類型不同,則也是重複聲明,函數不能僅僅基于不同的傳回類型而實作重載:

有些看起來不相同的形參表本質上是相同的:

在第一對函數聲明中,第一個聲明給它的形參命了名。形參名隻是幫助文檔,并沒有修改形參表。

在第二對函數聲明中,看似形參類型不同,但注意到 telno 其實并不是新類型,隻是 phone 類型的同義詞。typedef 給已存在的資料類型提供别名,但并沒有建立新的資料類型。是以,如果兩個形參的差别隻是一個使用 typedef 定義的類型名,而另一個使用 typedef 對應的原類型名,則這兩個形參并無不同。

在第三對中,形參清單隻有預設實參不同。預設實參并沒有改變形參的個數。無論實參是由使用者還是由編譯器提供的,這個函數都帶有兩個實參。

最後一對的差別僅在于是否将形參定義為 const。這種差異并不影響傳遞至函數的對象; 第二個函數聲明被視為第一個的重複聲明。其原因在于實參傳遞的方式。複制形參時并不考慮形參是否為 const——函數操縱的隻是副本。函數的無法修改實參。 結果, 既可将 const 對象傳遞給 const 形參, 也可傳遞給非 const 形參,這兩種形參并無本質差別。

值得注意的是,形參與 const 形參的等價性僅适用于非引用形參。有 const 引用形參的函數與有非 const 引用形參的函數是不同的。類似地,如果函數帶有指向 const 類型的指針形參, 則與帶有指向相同類型的非 const 對象的指針形參的函數不相同。

重載與在函數中局部聲明的名字将屏蔽

一般的作用域規則同樣适用于重載函數名。如果局部地聲明一個函數,則該函數将屏蔽而不是重載在外層作用域中聲明的同名函數。由此推論,每一個版本的重載函數都應在同一個作用域中聲明。

一般來說,局部地聲明函數是一種不明智的選擇。函數的聲明應放在頭檔案中。

作為例子,考慮下面的程式:

函數 foobar 中的 print(int) 聲明将屏蔽 print 的其他聲明,就像隻有一個有效的 print 函數一樣:該函數僅帶有一個 int 型形參。在這個作用域或嵌套在這個作用域裡的其他作用域中,名字 print 的任何使用都将解釋為這個print 函數執行個體。

調用 print 時,編譯器首先檢索這個名字的聲明,找到隻有一個 int 型形參的print 函數的局部聲明。一旦找到這個名字,編譯器将不再繼續檢查這個名字是否在外層作用域中存在, 即編譯器将認同找到的這個聲明即是程式需要調用的函數,餘下的工作隻是檢查該名字的使用是否有效。

另一種情況是,在與其他 print 函數相同的作用域中聲明 print(int),這樣,它就成為 print 函數的另一個重載版本。此時,所有的調用将以不同的方式解釋:

現在,編譯器在檢索名字 print 時,将找到這個名字的三個函數。每一個調用都将選擇與其傳遞的實參相比對的 print 版本。

繼續閱讀