C++ 重載、覆蓋與隱藏

首先看下這三個概念(http://www.cnblogs.com/fangyukuan/archive/2010/09/18/1829871.html 34題):
a.成員函數被重載的特徵:
(1)相同的範圍(在同一個類中);
(2)函數名字相同;
(3)參數不同;
(4)virtual 關鍵字可有可無。
b.覆蓋是指派生類函數覆蓋基類函數,特徵是:
(1)不同的範圍(分別位於派生類與基類);
(2)函數名字相同;
(3)參數相同;
(4)基類函數必須有virtual 關鍵字。
c.“隱藏”是指派生類的函數屏蔽了與其同名的基類函數,規則如下:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual 關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)

重載和覆蓋很好區分,然而隱藏具體而言是什麼意思呢?
根據上述規則,以下情況發生了隱藏:

class Parent{
public:
    void f1(){
        cout << "Parent::f1\n";
    }
    void f2(){
        cout << "Parent::f2\n";
    }
};
class Child : public Parent{
public:
    void f1(){
        cout << "Child::f1\n";
    }
    void f2(int x){
        cout << "Child::f2\n";
    }
};

Child::f1()和Child::f2(int)分別隱藏了Parent::f1()和Parent::f2()
注意如果Parent::f1()是virtual的,則變成了覆蓋
試着調用f1與f2:

Parent *p = new Child();
Child *c = new Child();
p->f1();
p->f2();
p->f2(1);//錯誤:函數中調用的參數太多
c->f1();
c->f2();//錯誤:函數中調用的參數太少
c->f2(1);

編譯成功的部分輸出爲:

Parent::f1
Parent::f2
Child::f1
Child::f1

綜上,我們可以發現:
a.發生隱藏時,雖然p指針指向的是Child的實例,但調用p->f1()時調用的不是Child的f1,而是Parent的f1
b.p指針無法調用Child::f2(int)
c.c指針無法調用Parent::f2()

因此,總結一下,在覆蓋中,用基類指針和派生類指針調用函數f1()時,系統都是執行的派生類函數f1(),而非基類的f1(),調用函數由指針指向的實例決定,這樣實際上就是完成“接口”的功能。
而在隱藏中,用基類指針和派生類指針調用函數f1()時,系統會進行區分,基類指針調用時,系統執行基類的f1(),而派生類指針調用時,系統“隱藏”了基類的f1(),執行派生類的f1(),也就是由指針的類型決定。

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