寫這篇文章的時候我還是不太确定重定義,重寫(覆寫),重載之間的确切的區分方法。下面是我今天的了解以及相關測試代碼,以待後觀!!
第一:簡單的子類重定義父類成員函數(函數三要素:傳回類型,函數名,參數):既然是重定義,函數名肯定是相同的,不然就沒有必要讨論了。三要素都相同,自然可以成立,現在的問題是傳回類型和參數是不是可以随意給,同樣能隐藏父類的成員函數?
(1)函數名,傳回類型,參數都相同
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a){
cout << "父類" << endl;
}
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;//第一種情況,函數名,傳回類型,參數都相同
}
};
int main()
{
CDerivedA ptr;
ptr.my();
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23

上面結果為調用子類成員函數輸出:子類
(2)函數名,傳回類型相同,參數不同,
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a,int b){
cout << "父類" << endl;
}
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;//參數個數不同
}
};
int main()
{
CDerivedA ptr;
ptr.my();//(1)給出一個參數
ptr.my(,);//(2)給出兩個參數,此時會報錯,函數不接受兩個參數。說明這個時候,子類并沒有繼承到父類void my(int a,int b)函數。
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24

一個參數的時候,調用子類的成員函數,輸出為:子類。兩個參數的時候報錯,說明基類方法已經被隐藏了(重新定義繼承函數,原來的函數被隐藏)。
(3)重定義繼承方法,應確定與原來的原型完全一緻——傳回類型協變
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a,int b){
cout << "父類" << endl;
}
virtual void Walk(){ cout << "CBase:Walk" << endl; }
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;
}
int Walk(){ cout << "CDerivedA:Walk" << endl; }//重定義類型與原來的類型不同
};
int main()
{
CDerivedA ptr;
ptr.Walk();
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25

輸出結果報錯:重寫虛函數傳回類型有差異,且不是來自“CBase::Walk”的協變
第二:虛函數重寫(覆寫)(傳回值類型必須相同)
(1)參數清單相同
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a,int b){
cout << "父類" << endl;
}
virtual void Walk(){ cout << "CBase:Walk" << endl; }
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;
}
void Walk(){ cout << "CDerivedA:Walk" << endl; }//重寫
};
int main()
{
CDerivedA ptr;
ptr.Walk();//輸出結果為:CDerivedA:Walk
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25

這是最常見的對父類虛函數重寫
參數清單不同
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a,int b){
cout << "父類" << endl;
}
virtual void Walk(int a){ cout << "CBase:Walk" << endl; }
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;
}
void Walk(){ cout << "CDerivedA:Walk" << endl; }//重寫
};
int main()
{
CDerivedA ptr;
ptr.Walk();//報錯:函數不接受 1 個參數
ptr.Walk();//輸出:CDerivedA:Walk
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26

對虛函數重新定義,但是由于參數清單不同,很容易了解為函數重載。如果是函數重載,那麼子類對象 應該繼承了父類被重載的成員函數,ptr.Walk(2);就不應該報錯。這說明,在這裡還是重定義,父類中同名函數被隐藏。
第三:父類重定義函數
#include <iostream>
using namespace std;
class CBase
{
public:
void my(int a,int b){
cout << "父類" << endl;
}
virtual void Walk(int a){ cout << "CBase:Walk" << endl; }
virtual void Walk(){ cout << "CBase::::::Walk" << endl; }
};
class CDerivedA : public CBase
{
public:
void my(int a ){
cout << "子類" << endl;
}
//void Walk(){ cout << "CDerivedA:Walk" << endl; }//重寫
};
int main()
{
CDerivedA ptr;
ptr.Walk();//輸出:CBase:Walk
ptr.Walk();//輸出:CBase::::::Walk
system("pause");
return ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27

結論:子類不能重載父類函數。即,重載發生在同一個類裡面
結論:
在類繼承中,重定義,重載。重定義函數名相同,傳回類型必須相同,參數清單可以相同,可以不同;重載,函數名相同,傳回類型和參數清單至少一個不同。
隻要子類出現與父類同名的函數,子類就不會繼承父類同名函數(隐藏)。當該同名函數在父類聲明為虛函數時(virtual),稱為重寫(覆寫),非虛函數時,稱為重定義