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(5);
    system("pause");
    return 0;
}

上面結果爲調用子類成員函數輸出:子類
(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(5);//(1)給出一個參數
    ptr.my(5,5);//(2)給出兩個參數,此時會報錯,函數不接受兩個參數。說明這個時候,子類並沒有繼承到父類void my(int a,int b)函數。
    system("pause");
    return 0;
}

一個參數的時候,調用子類的成員函數,輸出爲:子類。兩個參數的時候報錯,說明基類方法已經被隱藏了(重新定義繼承函數,原來的函數被隱藏)。
(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 0;
}

輸出結果報錯:重寫虛函數返回類型有差異,且不是來自“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 0;
}

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

參數列表不同

#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(2);//報錯:函數不接受 1 個參數
    ptr.Walk();//輸出:CDerivedA:Walk
    system("pause");
    return 0;
}

對虛函數重新定義,但是由於參數列表不同,很容易理解爲函數重載。如果是函數重載,那麼子類對象 應該繼承了父類被重載的成員函數,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(2);//輸出:CBase:Walk
    ptr.Walk();//輸出:CBase::::::Walk
    system("pause");
    return 0;
}

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

結論:
在類繼承中,重定義,重載。重定義函數名相同,返回類型必須相同,參數列表可以相同,可以不同;重載,函數名相同,返回類型和參數列表至少一個不同。
只要子類出現與父類同名的函數,子類就不會繼承父類同名函數(隱藏)。當該同名函數在父類聲明爲虛函數時(virtual),稱爲重寫(覆蓋),非虛函數時,稱爲重定義

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章