1.
區分:overload, override, Hide
Overload: 重載,指函數同名,但是參數個數不同、或者參數類型不同的多個實現。(如果參數相同但是僅僅返回值不同不是重載,編譯器會報錯。)
編譯器判斷重載函數:
第一步,是確定該調用中所考慮的重載函數的集合,該函數集合被稱為候選函數(candidant function)。所謂候選函數就是與被調用函數同名的函數。
第二步,分為兩動作:第一個動作是編譯器從第一步選出的候選函數中調出可行函數(viable function)。可行函數的函數參數個數與調用的函數參數個數相同,或者可行函數的參數可以多一些,但是多出來的函數參數都要有相關的缺省值;第二個動作是根據參數類型的轉換規則將被調用的函數實參轉換(conversion)成候選函數的實參。這裡本著充分利用參數類型轉換的原則,換句話說,盡可能的使用上參數類型轉換。當然轉換要以候選函數為轉換的目標。如果依照參數轉換規則沒有找到可行函數,則該調用就是錯誤的,則說沒有函數與調用匹配,屬於無匹配情況(no match function)。
第三步,從第二步中選出的可行函數中選出最佳可行函數(best match situation)。在最佳可行函數的選擇中,從函數實參類型到相應可行函數參數所用的轉化都要劃分等級,根據等級的劃分(ranked),最後選出最佳可行函數。
Override:(想不到比較貼切的翻譯)指在繼承時,父類函數聲明為vitual, 子類重新聲明和實現該函數(函數名和參數完全相同,返回值不做約束)。子類該函數可以聲明為virtual,也可以不加,不做限制,但是如果該子類還會繼續被重載,則最好也聲明為virtual。
Hide:繼承結構中的函數隱藏,指父類中聲明了函數,子類中聲明和定義了完全一致的函數,但是父類中函數沒有聲明為virtual,此時子類中的同名同參數函數會完全隱藏父類的函數。貌似和Override很像,但是其實現機制和Override完全不同,且會導致問題,應該避免使用。( virtual機制是使用虛表(vtable)實現的,虛表維護一個虛函數指針列表,但一個對象的某個虛函數被調用的時候,去虛表中查找並決定調用的是哪個函數,具體的實現,可以單獨一期博客講解。)
class Super{public: void go() { cout << "go() called on Super" << endl; }};
class Sub : public Super{public: void go() { cout << "go() called on Sub" << endl; }};
Sub mySub;mySub.go(); // output: go() called on Sub
Super& ref = mySub;ref.go(); //output: go() called on Super
也許你希望它會調用子類的函數,但這可能和你的預期完全不同。