我們知道過載函式中可以形參個數相同,但型別不同.而c++中雙允許做比較靈活的隱式型別轉換.所以呼叫函式時怎麼精確的匹配到要想的函式就是乙個問題.
此時一般分三個步驟去匹配
(1)先把所有過載函式找出來.把形參個數相同的先選出來.形參個數不同的就直接剔除掉.這相當於是海選,比如人家美女找老公,先看第一感覺,如果第一感覺不好.你進入海選的機會都沒有.
(2).然後從引數相同的候選的函式中去匹配形參.如果找到完全吻合的某乙個就大功告成了.就跟美女找到有錢又帥又有感覺的自然就非你不嫁了啊.但理想是美好的,現實是殘酷的,有時沒這麼完美的事.可能是帥得一踏糊塗,但也窮得一踏糊塗.或者有錢多得自己也數不清了,但醜得都不像人類了.
(3)找不到完全匹配的先做隱式型別轉換.如果匹配到唯一的乙個的話就也ok.這就跟美女可能只有乙個有錢的人,或者乙個長得帥的哥們有的挑.那就不用選了嘛.
(4)如果進行型別轉換後有幾個匹配咋整?要按照乙個規則進行判斷,哪個匹配最優就選哪個.這就跟美女在幾個帥的和有錢的中,最後發現乙個有很錢,但得還勉強能被當作人,不會被當作野人或大猩猩啥的.於是也ok
(5)在(4)中如果按照規則去匹配,結果還沒能得到唯一的選擇,而是得到兩個或多個符合條件的.這是計算機就傻眼了.直接報錯.不過人可聰明點.美女可能猶豫不決時就會徵求閨蜜們的意見.或者實在不行抓鬮算了.可不能猶豫不決讓煮熟的鴨子飛了啊.這是聰明女人的做法,但也有胸大無腦的女的啊.猶豫來猶豫去,結果那些男的都被其他女妖精們拐跑了.到時年已年容貌已不再就只能屈尊嫁給某個以前自己都看不上眼的男的了啊.日後心裡不平衡可能還偶爾給那男的戴戴綠帽啥的
用c#來舉個例子
假如有如下5個過載函式
void fun(string name) (1)
void fun(int num) (2)
void fun(long num) (3)
void fun(short sh, long on) {} (4)
void fun(long on, short sh) (5)
然後針對前面提到的5種匹配的情況來對照下.
(一)fun("arwen"); //匹配void fun(string name)
此時先挑選出函式1,2,3做為候選.然後直接匹配到(1),於是ok
(二)short num = 211;
fun(num); //匹配void fun(int num)
也是先匹配到1,2,3然後沒能找到完全匹配short型別的.於是就做隱式轉換.short可轉換成char,int,long.於是匹配到了(2)和(3).此時要按照規則來選哪乙個最合適了.一般是位元組數相差最少的是最優選擇.short是2個位元組,int是4,long是8.於是short轉換為int最優.於是ok就選(2).當然如果假設沒有函式(2)的話應就會選(3)的
(三)int num = 918;
fun(num , num); //匹配出錯.沒找到合適的.
它是先匹配到(4)和(5),然後做型別轉換int分別轉換成short和long就匹配到(4),int 分別轉換成long ,shot就匹配到(5).然後接著判斷哪個匹配最佳.結果傻眼了.兩個貌似一樣的好.
於是就報錯,說the call is ambiguous between the following methods or proerties.
c#由於對隱式型別轉換管得比較嚴,只有轉換時沒有任何精度損失時才可以轉.所以相對而言簡單一點.而c++任何數值型別都可以隱式轉.此時匹配起來更麻煩.更複雜.
不過原理完全一樣.
過載函式的好處是為我們取名省了很多事,不用給每乙個類似功能的函式取個啥有意義的名字.而且用起來也方便,只要記住乙個函式名字就行,具體呼叫的時候開發環境工具會給你提示要傳入的引數.
過載函式在c#中的用處更大一點,比如如果乙個函式要傳很多個引數進去,而用些引數不重要,使用者根據不關心.搞個預設值就行了.這就必須用過載函式讓使用者可以選擇傳不同的引數.而c++中由於有預設實參的功能,所以對過載函式的需求相對不那麼重要.
但通過上面的例子我們發現函式過載一多會容易出現匹配出錯的可能.所以如果過載的函式如果容易出現這種情況,比如有幾個引數都是數值型別.你可考慮別用過載,起個另外的函式名字得了.這是從寫過載函式的角度考慮.
而從函式使用者的角度考慮的話,我們呼叫函式時要看下函式要求傳啥引數,如果我們不是傳完全匹配的引數就先自己做下顯式轉換.然後再傳,這樣就不會出錯
在c++中有函式指標的概念.那我們宣告乙個函式指標時,然後匹配的話規則跟上面也是完全一樣.
不過c#中沒有指標的概念,但c#有個叫**(delegate)的機制.有點類似於函式指標,它就霸道很多,如果不能完全匹配就直接報錯,才不管啥先隱式轉換再匹配呢.
舉例delegate void mydelegate(short sh);//定義個**
然後有函式
void fun(int num)
宣告乙個**型別並初始化.mydelegate arwen = fun;
short sh = 12;
arwen(sh); //報錯.**表明它指向乙個返回值為void,形參為short型別的.但你是int型別的函式.所以不能匹配.
C 學習之四 過載C 操作符
為什麼要過載操作符 1 讓類表現得像內建資料型別一樣 2 能夠對程式中的表現有更多的控制 操作符過載的限制 1 不能增加新的操作符。2 有些操作符不能過載 3 不能改變操作符的元數 4 不能改變操作符的優先順序 5 不能重新定義內建型別的操作符 操作符過載中的選擇 a 方法或全域性函式 存在三種不同...
C 四 過載,重寫,重定義
2 重寫 3 重定義 4 重載重定義與重寫 過載指的是在同乙個作用域內,兩函式的函式名可以相同,但是引數不能完全相同,可以是引數型別不同或者是引數個數不同,至於返回值,不影響過載。1 函式過載從底層上來說,還是兩個不同的函式!函式會被編譯成 test int int inttest int a,in...
c 學習筆記3 過載
c 允許在同一作用域中的某個函式和運算子指定多個定義,分別稱為函式過載和運算子過載。過載宣告是指乙個與之前已經在該作用域內宣告過的函式或方法具有相同名稱的宣告,但是它們的引數列表和定義 實現 不相同。當您呼叫乙個過載函式或過載運算子時,編譯器通過把您所使用的引數型別與定義中的引數型別進行比較,決定選...