西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)編程開發(fā)VC|VC++ → C++函數(shù)名字重寫、重載、重定義程序?qū)嵗?/p>

C++函數(shù)名字重寫、重載、重定義程序?qū)嵗?/h1>

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2012/5/26 19:22:02字體大小:A-A+

作者:佚名點(diǎn)擊:155次評(píng)論:22次標(biāo)簽: 函數(shù)

  • 類型:編程輔助大。15KB語(yǔ)言:中文 評(píng)分:5.0
  • 標(biāo)簽:
立即下載

 C++中經(jīng)常出現(xiàn)函數(shù)名字一樣,但參數(shù)列表或返回值不同的函數(shù),要搞清楚函數(shù)的正確調(diào)用關(guān)系,需理清三個(gè)概念:重寫(override)、重載(overload)、重定義(redefine)。

一、三個(gè)基本概念

  1、重定義(redefine):派生類對(duì)基類的成員函數(shù)重新定義,即派生類定義了某個(gè)函數(shù),該函數(shù)的名字與基類中的函數(shù)名字一樣。

                特點(diǎn):(1)不在同一個(gè)作用域(分別位于基類、派生類)  (2)函數(shù)的名字必須相同  (3)對(duì)函數(shù)的返回值、形參列表無(wú)要求

                特殊情況:若派生類定義的該函數(shù)與基類的成員函數(shù)完全一樣(返回值、形參列表均相同),且基類的該函數(shù)為virtual,則屬于派生類重寫基類的虛函數(shù)。

                作用效果:若重新定義了基類中的一個(gè)重載函數(shù),則在派生類中,基類中該名字的函數(shù)(即其他所有重載版本)都被自動(dòng)隱藏,包括同名的虛函數(shù)。

  2、重載(overload):函數(shù)名字相同,但它的形參個(gè)數(shù)或者順序,或者類型不同,但是不能靠返回類型來(lái)判斷。

              特點(diǎn):(1)位于同一個(gè)類中  (2)函數(shù)的名字必須相同    (3)形參列表不同(可能是參數(shù)個(gè)數(shù)  or  類型  or  順序 不同),返回值無(wú)要求  

              特殊情況:若某一個(gè)重載版本的函數(shù)前面有virtual修飾,則表示它是虛函數(shù)。但它也是屬于重載的一個(gè)版本

                            不同的構(gòu)造函數(shù)(無(wú)參構(gòu)造、有參構(gòu)造、拷貝構(gòu)造)是重載的應(yīng)用

              作用效果和原理:編譯器根據(jù)函數(shù)不同的參數(shù)表,將函數(shù)體與函數(shù)調(diào)用進(jìn)行早綁定。重載與多態(tài)無(wú)關(guān),只是一種語(yǔ)言特性,與面向?qū)ο鬅o(wú)關(guān)。

  3、重寫(override):派生類重定義基類的虛函數(shù),即會(huì)覆蓋基類的虛函數(shù)   (多態(tài)性)

            特點(diǎn):(1)不在同一個(gè)作用域(分別位于基類、派生類)  (2)函數(shù)名、形參列表、返回值相同  (3)基類的函數(shù)是virtual

            特殊情況:若派生類重寫的虛函數(shù)屬于一個(gè)重載版本,則該重寫的函數(shù)會(huì)隱藏基類中與虛函數(shù)同名的其他函數(shù)。

            作用效果:父類的指針或引用根據(jù)傳遞給它的子類地址或引用,動(dòng)態(tài)地調(diào)用屬于子類的該函數(shù)。這個(gè)晚綁定過程只對(duì)virtual函數(shù)起作用

                         具體原理是由虛函數(shù)表(VTABLE)決定的,在第三節(jié)介紹。

二、程序?qū)嵗?/p>

1、兩個(gè)類:基類( 取名Test)和派生類( 取名XX)   名字不規(guī)范,哈哈隨便取得!

基類和派生類的結(jié)構(gòu)

//Base class
class Test
{
public:
    int a;

    Test()
    {
        cout<<"Test() 無(wú)參構(gòu)造函數(shù)!"<<endl;
    }

    Test(int data)
    {
        a = data;
        cout<<"Test(int data) 有參構(gòu)造函數(shù)!"<<endl;
    }

    Test(const Test &tmp)
    {
        a = tmp.a;
        cout<<"Test 拷貝構(gòu)造函數(shù)!!"<<endl;       
    }

    //基類中對(duì)函數(shù)名f,進(jìn)行了重載。其中最后一個(gè)重載函數(shù)為虛函數(shù)
    void f()const
    {
        cout<<"調(diào)用 void Test::f()"<<endl;
    }

    //overload
    int f(int data) const
    {
        cout<<"調(diào)用 Test f(int data)"<<endl;
        return 1;
    }

       //overload    虛函數(shù)
    virtual double f(int dataA,int dataB)
    {
        cout<<"調(diào)用 Test f(int a,int b)"<<endl;
        return dataA*dataB/2.0;
    }

};

class  XX: public Test
{
public:
    Test atest;//先調(diào)用基類的構(gòu)造函數(shù),然后對(duì)象成員的構(gòu)造函數(shù),最后才是派生類的構(gòu)造函數(shù)

    XX()
    {
        cout<<"XX() 無(wú)參構(gòu)造函數(shù)被調(diào)用!"<<endl;
    }

    //對(duì)基類的函數(shù)名f,進(jìn)行了重定義。則會(huì)隱藏基類中的其他f函數(shù)
    //redefine
    int  f() const
    {
        cout<<" 調(diào)用 XX f()函數(shù)"<<endl;
         return 1;
    }

    //重寫基類的虛函數(shù)
    //redefine   override
    double f(int dataA,int dataB)
    {
        cout<<"調(diào)用 XX f(int dataA,int dataB)函數(shù)"<<endl;
        return (dataA+dataB)/2.0;
    }
};

分析:基類class Test中定義了名為f的3個(gè)重載函數(shù),其中最后一個(gè)是虛函數(shù)

         派生類class  XX中對(duì)f進(jìn)行了重定義,所以會(huì)隱藏基類中名為f的版本。其中派生類的double f(int dataA,int dataB)屬于對(duì)虛函數(shù)的重寫

測(cè)試---主程序

int main()
{
//-----test 1------------------------
    cout<<"-------test 1------------"<<endl;
    //Base class
    Test aaTest;
       aaTest.f();
    aaTest.f(12);
    aaTest.f(10,20);

    //derived class
     XX d;
    d.f();
//    d.f(2); //error C2661: 'f' : no overloaded function takes 1 parameters
    d.f(10,20);

//--------test 2----------------------------------
    cout<<"-------test 2------------"<<endl;
    Test b = d;
    b.f();
    b.f(10,20);//調(diào)用的是基類的函數(shù),不發(fā)生多態(tài)

//--------test 3----------------------------------------
    cout<<"-------test 3------------"<<endl;
    Test &bR = d;//引用
    b.f();//f()不是虛函數(shù),調(diào)用基類的函數(shù)
    bR.f(10,20);//調(diào)用的是派生類的函數(shù),發(fā)生多態(tài)

//--------test 4--------------------------------------
    cout<<"-------test 4------------"<<endl;
    Test* pB = &d;
    b.f();
    pB->f(10,20);//調(diào)用的是派生類的函數(shù),發(fā)生多態(tài)

    return 1;
}

分析:(1)test 1中進(jìn)行了重載測(cè)試,根據(jù)傳遞參數(shù)的不一樣,調(diào)用不同的函數(shù)  (早綁定,與多態(tài)無(wú)關(guān))

         (2)test 2中Test b = d;定義了一個(gè)基類對(duì)象,用派生類對(duì)象來(lái)進(jìn)行初始化。這會(huì)調(diào)用基類的拷貝構(gòu)造函數(shù),生成基類的對(duì)象b,基類的拷貝構(gòu)造函數(shù)初始化b的VPTR,指向b的VTABLE。因此所有的函數(shù)調(diào)用都只發(fā)生在基類,不會(huì)產(chǎn)生多態(tài)。

            這是一個(gè)對(duì)象切片過程(參見《C++編程思想.第二版》P370),對(duì)象切片是當(dāng)它拷貝到一個(gè)新的對(duì)象時(shí),會(huì)去掉原來(lái)對(duì)象的一部分,而不是像使用指針或引用那樣簡(jiǎn)單地改變地址的內(nèi)容。

        (3)test 3和test 4中,定義的基類指針和引用,故會(huì)發(fā)生多態(tài)。

三、晚綁定原理:虛函數(shù)表

     編譯器會(huì)對(duì)每一個(gè)包含虛函數(shù)的類(或者從包含虛函數(shù)的基類派生的類)創(chuàng)建一個(gè)表(VTABLE),里面存放特定類的虛函數(shù)的地址。然后編譯器秘密地放置一指針vpointer(VPTR),指向這個(gè)對(duì)象的vtable。當(dāng)通過基類指針做虛函數(shù)調(diào)用時(shí)(即多態(tài)調(diào)用時(shí)),編譯器靜態(tài)地插入能取得這個(gè)VPTR并在VTABLE表中查找函數(shù)地址的代碼,這樣就能調(diào)用正確的函數(shù)并引起晚綁定的發(fā)生。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(22)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)