》 重寫,重定義經常與繼承和虛繼承一起使用,那麼我們一步一步來,先看看重寫,重定義到底是什麼樣子的呢?
》重載:
1.它在同一個作用域中
2.函數名必須相同
3.參數個數,類型,順序不同
4.返回值不作要求
5.virtual關鍵字不作要求
》重寫(覆蓋):
1.不在同一個作用域中(即基類與子類中)
2.函數名相同,返回值相同,參數也相同
3.只是在基類同名函數前必須有virtual關鍵字不能有static。
這時派生類的重寫函數就會覆蓋基類中的同名函數。
》重定義(隱藏):
1.不再同一個作用域(即基類與子類中)
2.函數名相同
3.返回值不作要求
4. 參數相同時,基類同名函數前不能有virtual關鍵字
參數不同時,基類同名函數前有無virtual關鍵字不作要求。
這時派生類的重寫函數就會隱藏基類中的同名函數。
在這裏我引申一個新的概念叫做協變:當函數不在同一個作用域,函數名相同並且基類函數前有virtual關鍵字但是返回值返回的是基類對象的指針或者引用時就認爲是協變。
舉個例子:
class Base { public: virtual void f1(); virtual void f2(); void f3(); void f4(); }; class Deriver :public Base { public : void f1(); //函數重寫,這裏的virtual可以不寫,基類函數覆蓋 void f2(int x);//重定義 char f3(); //重定義 void f4(); //重定義 }; void Base::f1() { cout << "--Base-f1--" << endl; } void Base::f2() { cout << "--Base-f2--" << endl; } void Base::f3() { cout << "--Base-f3--" << endl; } void Base::f4() { cout << "--Base-f4--" << endl; } void Deriver::f1() { cout << "--Deriver-f1--" << endl; } void Deriver::f2(int x) { cout << "--Deriver-f2--" << endl; } char Deriver::f3() { cout << "--Deriver-f3--" << endl; } void Deriver::f4() { cout << "--Deriver-f4--" << endl; } int main() { Base d1, *bp; Deriver d2; bp = &d2; bp->f1(); bp->f2(); bp->f4(); return 0; }
結果:
1.Derived類中的函數f1()是對Base類中函數f1()的重寫,即使用了虛函數特性。
2.Derived類中的函數f2()是對Base類中函數f2()的隱藏,即重定義了。
3.因爲Base類的函數f3()和f4()沒有定義爲virtual虛函數,所以Derived類的函數f3()和f4()是對Base::c()的重定義。
4.bp指針是一個指向Base類型的指針,但是它實際指向了一個Derived的空間,這裏對pd調用函數的處理(多態性)取決於是否重寫(虛函數特性)了函數,若沒有,則依然調用基類。
5.只有在通過基類指針或基類引用 間接指向派生類類型時多態性纔會起作用。