天天看點

C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

寫這篇文章的時候我還是不太确定重定義,重寫(覆寫),重載之間的确切的區分方法。下面是我今天的了解以及相關測試代碼,以待後觀!!

第一:簡單的子類重定義父類成員函數(函數三要素:傳回類型,函數名,參數):既然是重定義,函數名肯定是相同的,不然就沒有必要讨論了。三要素都相同,自然可以成立,現在的問題是傳回類型和參數是不是可以随意給,同樣能隐藏父類的成員函數?

(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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

上面結果為調用子類成員函數輸出:子類

(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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

一個參數的時候,調用子類的成員函數,輸出為:子類。兩個參數的時候報錯,說明基類方法已經被隐藏了(重新定義繼承函數,原來的函數被隐藏)。

(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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

輸出結果報錯:重寫虛函數傳回類型有差異,且不是來自“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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

這是最常見的對父類虛函數重寫

參數清單不同

#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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

對虛函數重新定義,但是由于參數清單不同,很容易了解為函數重載。如果是函數重載,那麼子類對象 應該繼承了父類被重載的成員函數,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
C++父類子類間函數重定義,虛函數重寫(覆寫)以及重載

結論:子類不能重載父類函數。即,重載發生在同一個類裡面

結論:

在類繼承中,重定義,重載。重定義函數名相同,傳回類型必須相同,參數清單可以相同,可以不同;重載,函數名相同,傳回類型和參數清單至少一個不同。

隻要子類出現與父類同名的函數,子類就不會繼承父類同名函數(隐藏)。當該同名函數在父類聲明為虛函數時(virtual),稱為重寫(覆寫),非虛函數時,稱為重定義