1 重寫(覆蓋)override
override是重寫(覆蓋)了一個方法,以實現不同的功能。一般用於子類在繼承父類時,重寫(覆蓋)父類中的方法。函數特征相同,但是具體實現不同。
重寫需要注意:
- 被重寫的函數不能是static的,必須是virtual的
- 重寫函數必須有相同的類型,名稱和參數列表
- 重寫函數的訪問修飾符可以不同。盡管virtual是private的,派生類中重寫改寫為public、protect也是可以的
2 重載overload
overload是重載,一般是在一個類實現若干重載的方法,這些方法的名稱相同而參數形式不同。但是不能靠返回類型來判斷。
重載需要注意:
- 位於同一個類中
- 函數的名字必須相同
- 形參列表不同
- 若一個重載版本的函數面前有virtual修飾,則表示他是虛函數,但他也是屬於重載的一個版本
- 不同的構造函數(無參構造、有參構造、拷貝構造)是重載的應用
3 重定義redefining
派生類對基類的成員函數重新定義,即派生類定義了某個函數,該函數的名字與基類中函數名字一樣。
重定義也叫做隱藏,子類重定義父類中有相同名稱的非虛函數(參數可以不同)。如果一個類,存在和父類相同的函數,那么這個類將會覆蓋其父類的方法,除非你在調用的時候,強制轉換為父類類型,否則試圖對子類和父類做類似重載的調用時不能成功的。
重定義需要注意:
- 不在同一個作用域(分別位於基類、派生類)
- 函數的名字必須相同
- 對函數的返回值、形參列表無要求
- 若派生類定義該函數與基類的成員函數完全一樣(返回值、形參列表均相同),且基類的該函數為virtual,則屬於派生類重寫基類的虛函數
- 若重新定義了基類中的一個重載函數,則在派生類中,基類中該名字函數(即其他所有重載版本)都會被自動隱藏,包括同名的虛函數
4 多態polymorphism
多態的概念比較復雜,一種不嚴謹的說法是:繼承是子類使用父類的方法,而多態是父類使用子類的方法。
一般我們使用多態是為了避免在父類里大量重載引起代碼臃腫且難於維護。
多態分為兩類:靜態多態性和動態多態性,以前學過的函數重載和運算符重載實現的多態性屬於靜態多態性,在程序編譯時系統就能決定調用哪個函數,因此靜態多態性又稱為編譯時的多態性。靜態多態性是通過函數的重載實現的。動態多態性是在程序運行過程中才動態地確定操作所針對的對象。它又稱運行時的多態性。動態多態性是通過虛函數實現的。
下面列舉一個實例來說明他們:
class Base
{
private:
virtual void display() {cout<<"Base display()"<<endl;}
void say() {cout<<"Base say()"<<endl;}
public:
void exec() {display();say();}
void fun1(string a) {cout<<"Base fun1(string)"<<endl;]
void fun1(int a) {cout<<"Base fun1(int)"<<endl;}//overload,兩個fun1函數在Base類的內部被重載
};
class ChildA:public Base
{
public:
void display() {cout<<"ChildA display()"<<endl;}//override,基類中的display為虛函數,故此處為重寫(覆蓋)
void fun1(int a,int b) {cout<<"ChildA fun1(int,int)"<<endl;}//redefining,fun1函數在Base類中不為虛函數,故此處為重定義
void say() {cout<<"ChildA say()"<<endl;}//redefining
};
class ChildB:pubic Base
{
public:
void fun1(int a) {cout<<"ChildB fun1(int)"<<endl;}//redefining
};
int main()
{
ChildA a;
Base* b=&a;
b->exec(); //display():version of DeriveA call(polymorphism) //say():version of Base called(allways )
//b里邊的函數display被A類重寫(覆蓋),say還是自己的
a.exec(); //same result as last statement
a.say();
DeriveB c;
c.f1(1); //version of DeriveB called
}
執行結果:
ChildA display()
Base say()
ChildA display()
Base say()
ChildA say()
ChildB fun1(int)
總結:
重寫(覆蓋)
- 是指派生類函數重寫(覆蓋)基類函數
- 不同的范圍,分別位於基類和派生類中
- 函數的名字相同
- 參數相同
- 基類函數必須有virtual關鍵字
重載
- 成員函數
- 形同的范圍(在同一個類中)
- 函數的名字相同
- virtual關鍵字可有可無
重定義(隱藏)
- 派生類屏蔽了與其同名的基類函數
- 如果派生類的函數和基類的函數同名,但是參數不同,此時,不管有無virtual,基類的函數被隱藏
- 如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有關鍵字,此時,基類的函數被隱藏