1、Override、Overload、Redefine
-
Overload
多載只能發生在類內部,不能發生在子類和父類的繼承中,具體來說,如果子類中有父類同名、同回傳值型別,但是不同引數串列,這兩個在不同類的函式是不能發生多載的, -
Override
重寫即就是子類將父類中的方法進行改寫,在實體化Parent *p = new Son(),即創建指標型別為父類,指向子類空間的指標,能看到重寫和重定義的區別, -
Redefine
重定義亦是發生在在繼承的程序中,這個和重寫容易發生混淆,主要區別根據父類中被重寫或重定義的成員函式有無virtual關鍵字來討論,如果沒有virtual關鍵字,只要函式名相同,都會發生函式的重定義,或者說隱藏,即子類成員函式隱藏父類同名的成員函式;如果有virtual關鍵字,首先要保證回傳值型別要相同(個人在測驗中發現,在子類中,只有將保持回傳值型別、函式名相同,才能進行下一步的重寫或重定義),再判斷是發生多載還是重定義,如果引數串列相同,則發生重寫,如果不相同,則是重定義,
2、三者之間的區別
-
多載 overload
- 發生在相同的作用域(子類和父類不在同一個作用域)
- 函式名要相同
- 引數串列不同,包括引數型別、引數個數、引數的順序
- 有無
virtual關鍵字都可以發生 - 回傳值可以不同
-
重寫 override
- 不同的作用域(兩個同名函式分別在父類和子類)
- 相同的函式名
- 相同的引數串列
- 被重寫父類中的成員函式必須有關鍵字'virtual'
- 相同的回傳值型別
- 被重寫的成員函式訪問權限可以被修改,
public、protect或者其他,
-
重定義 redefine
- 不同的作用域
- 函式名相同
- 回傳值型別可以不同(沒有關鍵字
virtual的情況),但是如果有virtual關鍵字,必須保證回傳型別相同,否則編譯報錯, - 父類函式沒有關鍵字
virtual,引數串列可同可不同;父類函式有關鍵字virtual,引數串列必須不同,
舉個例子說明一下:
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()
分別創建子類、父類、指標型別為父類指向子類空間的指標,(1)父類中的func2發生多載,主要在父類內部產生(應該說相同作用域),因為給s.func2('c')傳入字符的時候,只會呼叫子類函式,不會呼叫父類的func2(char c),而子類中的func2對父類的func2發生了重定義,并對其做了隱藏,所以呼叫的時候才會呼叫到子類的func2(double ),從s.func1()、s.func2()、s.func3()都發生了重定義,所以在繼承的程序中,如果沒有virtual關鍵字,只要函式名相同,不管引數型別、回傳值型別,都會發生重定義,(2)針對有virtual關鍵字的情況,在函式名相同的情況下,首先要保證回傳值型別相同,否則編譯不過,如果引數串列相同,則發生重寫,不同則發生重定義,例如bp->func4()和bp->func5(),這里bp呼叫函式的處理取決于是否重寫的函式(虛函式的特性),
參考文獻
- Overload/override/redefining in C++ classes
- c++ overload override redefine
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266194.html
標籤:C++
