1、Override、Overload、Redefine
-
Overload
重載只能發(fā)生在類內(nèi)部,不能發(fā)生在子類和父類的繼承中。具體來(lái)說(shuō),如果子類中有父類同名、同返回值類型,但是不同參數(shù)列表,這兩個(gè)在不同類的函數(shù)是不能發(fā)生重載的。
-
Override
重寫即就是子類將父類中的方法進(jìn)行改寫。在實(shí)例化Parent *p = new Son() ,即創(chuàng)建指針類型為父類,指向子類空間的指針,能看到重寫和重定義的區(qū)別。
-
Redefine
重定義亦是發(fā)生在在繼承的過(guò)程中,這個(gè)和重寫容易發(fā)生混淆。主要區(qū)別根據(jù)父類中被重寫或重定義的成員函數(shù)有無(wú)virtual 關(guān)鍵字來(lái)討論。如果沒(méi)有virtual 關(guān)鍵字,只要函數(shù)名相同,都會(huì)發(fā)生函數(shù)的重定義,或者說(shuō)隱藏,即子類成員函數(shù)隱藏父類同名的成員函數(shù);如果有virtual 關(guān)鍵字,首先要保證返回值類型要相同(個(gè)人在測(cè)試中發(fā)現(xiàn),在子類中,只有將保持返回值類型、函數(shù)名相同,才能進(jìn)行下一步的重寫或重定義),再判斷是發(fā)生重載還是重定義,如果參數(shù)列表相同,則發(fā)生重寫,如果不相同,則是重定義。
2、三者之間的區(qū)別
-
重載 overload
- 發(fā)生在相同的作用域(子類和父類不在同一個(gè)作用域)
- 函數(shù)名要相同
- 參數(shù)列表不同,包括參數(shù)類型、參數(shù)個(gè)數(shù)、參數(shù)的順序
- 有無(wú)
virtual 關(guān)鍵字都可以發(fā)生
- 返回值可以不同
-
重寫 override
- 不同的作用域(兩個(gè)同名函數(shù)分別在父類和子類)
- 相同的函數(shù)名
- 相同的參數(shù)列表
- 被重寫父類中的成員函數(shù)必須有關(guān)鍵字'virtual'
- 相同的返回值類型
- 被重寫的成員函數(shù)訪問(wèn)權(quán)限可以被修改,
public 、protect 或者其他。
-
重定義 redefine
- 不同的作用域
- 函數(shù)名相同
- 返回值類型可以不同(沒(méi)有關(guān)鍵字
virtual 的情況),但是如果有virtual 關(guān)鍵字,必須保證返回類型相同,否則編譯報(bào)錯(cuò)。
- 父類函數(shù)沒(méi)有關(guān)鍵字
virtual ,參數(shù)列表可同可不同;父類函數(shù)有關(guān)鍵字virtual ,參數(shù)列表必須不同。
舉個(gè)例子說(shuō)明一下:
class Base{
public:
int param3 = 0;
void func1(){cout<<"This is Base::func1()"<<endl;}
void func2(int a){cout<<"This is Base::func2(int a)"<<endl;}
void func2(char c){cout<<"This is Base::func2(char c)"<<endl;}
void func3(){cout<<"This is Base::func3()"<<endl;}
virtual void func4(){cout<<"This is Base::func4()"<<endl;}
virtual void func5(){cout<<"This is Base::func5()"<<endl;}
virtual int func6(){cout<<"This is int Base::func6()"<<endl;}
};
class Son: public Base
{
public:
int param = 1;
int func1(){cout<<"This is Son::func1()"<<endl;}
void func2(double e){cout<<"This is Son::func2()"<<endl;}
void func3(){cout<<"This is Son::func3()"<<endl;}
void func4(){cout<<"This is Son::func4()"<<endl;}
void func5(int a){cout<<"This is Son::func5(int a)"<<endl;}
// double func6(){cout<<"This is Son::func6()"<<endl;}
};
int main() {
Son s;
Base b;
Base *bp = new Son();
s.func1();
s.func2(1.1);
s.func2('c');
s.func4();
s.func5(2);
cout<<"--------------------------------"<<endl;
b.func1();
b.func2(1);
b.func2('c');
b.func3();
cout<<"--------------------------------"<<endl;
bp->func1();
bp->func2(1);
bp->func2('e');
bp->func3();
bp->func4();
bp->func5();
return 0;
}
輸出如下:
This is Son::func1()
This is Son::func2()
This is Son::func2()
This is Son::func4()
This is Son::func5(int a)
--------------------------------
This is Base::func1()
This is Base::func2(int a)
This is Base::func2(char c)
This is Base::func3()
--------------------------------
This is Base::func1()
This is Base::func2(int a)
This is Base::func2(char c)
This is Base::func3()
This is Son::func4()
This is Base::func5()
分別創(chuàng)建子類、父類、指針類型為父類指向子類空間的指針。(1)父類中的func2發(fā)生重載,主要在父類內(nèi)部產(chǎn)生(應(yīng)該說(shuō)相同作用域),因?yàn)榻os.func2('c') 傳入字符的時(shí)候,只會(huì)調(diào)用子類函數(shù),不會(huì)調(diào)用父類的func2(char c) 。而子類中的func2 對(duì)父類的func2 發(fā)生了重定義,并對(duì)其做了隱藏,所以調(diào)用的時(shí)候才會(huì)調(diào)用到子類的func2(double ) 。從s.func1() 、s.func2() 、s.func3() 都發(fā)生了重定義,所以在繼承的過(guò)程中,如果沒(méi)有virtual 關(guān)鍵字,只要函數(shù)名相同,不管參數(shù)類型、返回值類型,都會(huì)發(fā)生重定義。(2)針對(duì)有virtual 關(guān)鍵字的情況,在函數(shù)名相同的情況下,首先要保證返回值類型相同,否則編譯不過(guò),如果參數(shù)列表相同,則發(fā)生重寫,不同則發(fā)生重定義,例如bp->func4() 和bp->func5() ,這里bp調(diào)用函數(shù)的處理取決于是否重寫的函數(shù)(虛函數(shù)的特性)。
參考文獻(xiàn)
|