一. 簡介
•Overload: 重載,指函數同名,但是參數個數不同、或者參數類型不同的多個實現。(如果參數相同但是僅僅傳回值不同不是重載,編譯器會報錯。)
編譯器判斷重載函數:
•第一步,是確定該調用中所考慮的重載函數的集合,該函數集合被稱為候選函數(candidant function)。所謂候選函數就是與被調用函數同名的函數。
•第二步,分為兩動作:第一個動作是編譯器從第一步選出的候選函數中調出可行函數(viable function)。可行函數的函數參數個數與調用的函數參數個數相同,或者可行函數的參數可以多一些,但是多出來的函數參數都要有相關的預設值;第二個動作是根據參數類型的轉換規則將被調用的函數實參轉換(conversion)成候選函數的實參。這裡本著充分利用參數類型轉換的原則,換句話說,儘可能的使用上參數類型轉換。當然轉換要以候選函數為轉換的目標。如果依照參數轉換規則沒有找到可行函數,則該調用就是錯誤的,則說沒有函數與調用匹配,屬於無匹配情況(no match function)。
•第三步,從第二步中選出的可行函數中選出最佳可行函數(best match situation)。在最佳可行函數的選擇中,從函數實參類型到相應可行函數參數所用的轉化都要劃分等級,根據等級的劃分(ranked),最後選出最佳可行函數。
•Override:(想不到比較貼切的翻譯)指在繼承時,父類函式宣告為 virtual , 子類重新聲明和實現該函數(函數名和參數完全相同,傳回值不做約束)。子類該函數可以聲明為 virtual ,也可以不加,不做限制,但是如果該子類還會繼續被重載,則最好也聲明為 virtual 。正是因為有virtual和Override的機制,C++才能夠實現多態。
•Hide:繼承結構中的函數隱藏,指父類中聲明了函數,子類中聲明和定義了完全一致的函數,但是父類中函數沒有聲明為vitual,此時子類中的同名同參數函數會完全隱藏父類的函數。貌似和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
也許你希望它會調用子類的函數,但這可能和你的預期完全不同。
二. 總結
重載overload,這個概念是大家熟知的。在同一可訪問區內被聲名的幾個具有不同參數列的(參數的類型、個數、順序不同)同名函數,程式會根據不同的參數列來確定具體調用哪個函數,這種機制就是重載。重載不關心函數的傳回值類型,即傳回型別不同無法構成重載。此外,C++ 中的const成員函數也可以構成overload。
總結一下重載的特徵:
1、處在相同的空間中,即相同的範圍內;
2、函數名相同;
3、參數不同,即參數個數不同,或相同位置的參數類型不同;
4、const成員函數可以和非const成員函數形成重載;
5、virtual關鍵字、傳回型別對是否夠成重載無任何影響。
覆蓋override,是指衍生類別中存在重新定義的函數,其函數名、參數列、傳回值類型必須同父類中的相對應被覆蓋的函數嚴格一致,覆蓋函數和被覆蓋函數只有函數體(花括弧中的部分)不同,當衍生類別對象調用子類中該同名函數時會自動調用子類中的覆蓋版本,而不是父類中的被覆蓋函數版本,這種機制就叫做覆蓋,特徵是:
1、不同的範圍(分別位於衍生類別與基類);
2、函數名字相同;
3、參數相同;
4、基類函數必須有virtual關鍵字。
針對上述兩個概念,還有一個隱藏hide。所謂的隱藏,指的是衍生類別類型的對象、指標、引用訪問基類和衍生類別都有的同名函數時,訪問的是衍生類別的函數,即隱藏了基類的同名函數。隱藏規則的底層原因其實是C++的名字解析過程。在繼承機制下,衍生類別的類域被嵌套在基類的類域中。衍生類別的名字解析過程如下:
1、首先在衍生類別類域中尋找該名字。
2、如果第一步中沒有成功尋找到該名字,即在衍生類別的類域中無法對該名字進行解析,則編譯器在外圍基類類域對尋找該名字的定義。
總結一下隱藏的特徵:
1、如果衍生類別的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
2、如果衍生類別的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)。