C++多態 重寫 重載 隱藏之間的關係

C++多態性是通過虛函數來實現的,虛函數允許子類重新定義成員函數,而子類重新定義父類的做法稱爲覆蓋(override),或者稱爲重寫。

重寫:子類重定義基類中的virtual函數,通過子類指針或引用指向子類對象時,調用的是子類中的的函數。

重載:一個類內部的具有不同形參的函數構成重載,不涉及基類和子類。

隱藏這裏“隱藏”是指派生類的函數屏蔽了與其同名的基類函數或成員變量

對於基類子類同名函數來說,只要不是virtual重寫,其他的子類同名函數都將隱藏基類的同名函數,即:
(1)如果派生類的函數與基類的函數同名,但是參數不同。此時,不論有無virtual
關鍵字,基類的函數將被隱藏(注意別與重載混淆)。
(2)如果派生類的函數與基類的函數同名,並且參數也相同,但是基類函數沒有virtual
關鍵字。此時,基類的函數被隱藏(注意別與覆蓋混淆)。

下面貼一段代碼:

#include <iostream>
#include <stdio.h>
using namespace std;

class TestA{
public:
    TestA():mCount(0){}
    virtual ~TestA() {printf("release A\n");}
public:
    virtual void init() {printf("this is A init\n");mCount = 5/10;}
    virtual void increment() {printf("this is A++\n"); mCount++;}
    virtual void print() {printf("this is A, count = %d\n",mCount);}
private:
    int mCount;
};
class TestB : public TestA{
public:
    TestB():mCount(0){}
    virtual ~TestB() {printf("release B\n");}
public:
    virtual void init() {printf("this is B init\n");mCount = 10;}
    virtual void print() {printf("this is B, count = %d\n",mCount);}
private:
    int mCount;
};
int main(void)
{
    TestB *pB = new TestB();
    pB->init();  // mCount = 10
    pB->increment();//重點在這裏,TestB中並沒重寫虛函數increment ,調用了TestA中
                    //函數,並且使TestA::mCount數據成員自增+1, 然後再調用TestB中的打印
                    // TestB::mCount 爲10,並不是11, 這裏要分清楚是哪一個數據成員
    pB->print();   //打印的是TestB中的mCount 10


    TestA *pA = (TestA*)pB;// 這裏涉及到多態,當用基類的指針指向派生類對象時,派生類中有虛函數,則會有一個虛指針,
    //在分配的TestB內存塊的最開頭的前四個字節,指向TestB中存在的虛函數首地址,
    //可以在內存中用看pB的值,然後看內存,前四個字節爲虛指針,
    //所以pA指向了pB的虛指針所在內存塊的地址,因此這裏和上面情況其實是一樣的
    pA->init();//TestB::mCount爲10
    pA->increment();//TestA::mCount + 1
    pA->print();//打印的是TestB中的mCount 10


    TestA aA = *pB;//此處將*pB中已經對TeseA中的數據成員初始化了,並且將該值給了aA中的數據成員
                //下面都是調用TestA中的函數
    aA.print();//這裏TestA::mCount爲2
    aA.init(); //TestA::mCount又被重置0
    aA.increment();//TestA::mCount + 1
    aA.print();//TestA::mCount 爲 1

    delete pB;// pB爲派生類對象指針,且TestA和TestB的析構均爲虛析構,

            // 會先調用B的析構,然後A的析構, 最後應用程序結束時,調用aA的析構函數

            //   即Release B  ReleaseA ReleaseA
}
結果:


如果還不懂,可以參考以下兩篇文章:

http://blog.csdn.net/hackbuteer1/article/details/7475622

http://blog.csdn.net/foruok/article/details/37996805

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