重寫(Override)與隱藏(hide)的區別

來源:互聯網
上載者:User

重寫必須滿足的條件:
1. 基類中的函數使用virtual修飾,即基類中的函數為虛函數;
2. 衍生類別中與基類中的這個virtual函數要有相同的函數原型(即:傳回型別相同、函數名相同、形參列表相同);
下面我們看個簡單的程式:

#include <iostream>using std::cout;using std::endl;class Person{public:  virtual void Study()  {      cout << "這是基類中的方法" << endl;  }};class Man : public Person{public:    virtual void Study()    {        cout << "這是衍生類別中的方法" << endl;    }};int main(void){    Person *p = new Man;    p -> Study();// 輸出結果:這是衍生類別中的方法    return 0;}

Man類中的Study()函數對Person類中的Study()函數進行了重寫。

也許有些人認為:傳回型別可以不同,這個我們可以做個測試,就是將Man類中的Study()方法改為傳回值為int類型:

virtual void Study(){cout << "這是衍生類別中的方法" << endl;return 0;}

再次編譯,我們會發現,程式編譯都不能通過,提示傳回型別衝突,重寫錯誤。

所以,重寫(Override)或覆蓋只會發生在多態中。對於基類中的非virtual函數,在衍生類別中重新定義只會導致隱藏。

隱藏:指的是衍生類別中的函數屏蔽了基類中的函數。

隱藏的規則:
1. 對於基類中的非virtual函數,如果衍生類別中存在和基類中相同的函數名,而不管傳回值和形參列表是否相等;都會導致基類中的所有同名函數被衍生類別隱藏;
2. 對於基類中的virtual函數,如果衍生類別中存在和基類中相同的函數名,而且形參列表不同,就會導致基類中的所有同名的virtual函數被衍生類別隱藏;

注意:如果衍生類別中的函數和基類中的同名的virtual函數具有相同的形參列表和不同的傳回值,那麼將不會隱藏基類中的函數,直接導致編譯錯誤(原因:編譯器此時會認為你是在重寫方法,而不是隱藏,只是傳回型別寫錯了)。

下面我們看一個簡單的程式:

#include <iostream>using std::cout;using std::endl;class Person{public:    void Eat()    {        cout << "這是基類中的Eat方法" << endl;    }    void Work()    {        cout << "這是基類中不帶參數、傳回值為void的Work函數" << endl;    }    void Work(int a)    {         cout << "這是基類中帶一個參數、傳回值為void的Work函數" << endl;    }    virtual void Study()    {        cout << "這是基類中不帶參數的虛方法" << endl;    }    virtual void Study(int a)    {         cout << "這是基類中有一個參數的虛方法" << endl;    }};class Man : public Person{public:    int Work()    {        cout << "這是衍生類別中不帶參數、傳回值為int的Work函數" << endl;        return 0;    }    virtual  void Study(int a, int b)    {        cout << "這是衍生類別中虛的方法" << endl;    }};int main(void){    Man m;    m.Eat(); // m.Study();      //該函數已被衍生類別中定義的Study(int a, int b)隱藏,調用會導致編譯錯誤 // m.Study(1);     //該函數已被衍生類別中定義的Study(int a, int b)隱藏,調用會導致編譯錯誤    m.Study(1, 2);    m.Work(); // m.Work(1);      //該函數已被衍生類別隱藏中定義的Work()隱藏,調用會導致編譯錯誤    return 0;}

分析:在衍生類別中,沒有定義Eat()方法,所以衍生類別可以正常的調用基類中的Eat()方法,但是後面的Study()方法,在衍生類別中對其進行了定義,雖然函數原型不同,但也隱藏了基類中的所有名為Study()的函數,需要注意的是:如果衍生類別中的函數和基類中的同名的virtual函數具有相同的形參列表和不同的傳回值,那麼將不會隱藏基類中的函數,直接導致編譯錯誤(原因:編譯器此時會認為你是在重寫方法,而不是隱藏,只是傳回型別寫錯了)。關於這一點,你可以在Man中添加一個int
Study()函數試一下。對於Work()函數,同樣是由於在衍生類別中定義了一個同名的函數,導致基類中重載的一組Work()函數都被屏蔽。

對於隱藏,我們從字面意思也可以看出,只是將基類中的同名的函數屏蔽了,並沒有將其銷毀,所以我們還是可以對其進行調用的。

主要有以下三種方法:

1. 在衍生類別中的函數中調用基類中的同名函數,比如:

    virtual  void Study()    {        Person::Study();           }

2. 在衍生類別中定義函數的前面使用using關鍵字顯式地聲明;

    using Person::Study;    virtual void Study()    {        cout << "這是基類中不帶參數的虛方法" << endl;    }

3. 採用衍生類別對象.基類名::基類中的方法;直接調用;例如:對於上面的程式,如果我們要調用基類中的Study()方法,我們可以這樣才調用:m.Person::Study();

通過這三種方式,我們就可以訪問被衍生類別屏蔽了的基類中定義的函數。

總結:所謂重寫(或叫覆蓋),指的是衍生類別對基類中的虛函數進行方法體的改寫(要求函數原型相同);而隱藏指的是,衍生類別中的函數屏蔽了基類中同名的所有函數。(對virtual函數,要求函數名相同,形參列表不同;對非virtual函數,函數名相同即可)。注意:在繼承中不涉及重載的概念,因為重載最基本的要求是:在相同的範圍中,而繼承顯然屬於不同範圍。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.