亚洲免费乱码视频,日韩 欧美 国产 动漫 一区,97在线观看免费视频播国产,中文字幕亚洲图片

      1. <legend id="ppnor"></legend>

      2. 
        
        <sup id="ppnor"><input id="ppnor"></input></sup>
        <s id="ppnor"></s>

        二級考試C++基礎(chǔ):虛函數(shù)與多態(tài)性

        字號:

        因為魚的呼吸是吐泡泡,和一般動物的呼吸不太一樣,所以我們在fish類中重新定義breathe方法。我們希望如果對象是魚,就調(diào)用fish類的breathe()方法,如果對象是動物,那么就調(diào)用animal類的breathe()方法。程序代碼如例2-16所示(EX08.CPP)。
            例2-16
            #include
            class animal
            {
            public:
            void eat()
            {
            cout<<"animal eat"<    }
            void sleep()
            {
            cout<<"animal sleep"<    }
            void breathe()
            {
            cout<<"animal breathe"<    }
            };
            class fish:public animal
            {
            public:
            void breathe()
            {
            cout<<"fish bubble"<    }
            };
            void fn(animal *pAn)
            {
            pAn->breathe();
            }
            void main()
            {
            animal *pAn;
            fish fh;
            pAn=&fh;
            fn(pAn);
            }
            我們在fish類中重新定義了breathe()方法,采用吐泡泡的方式進行呼吸。接著定義了一個全局函數(shù)fn(),指向animal類的指針作為fn()函數(shù)的參數(shù)。在main()函數(shù)中,定義了一個fish類的對象,將它的地址賦給了animal類的指針變量pAn,然后調(diào)用fn()函數(shù)??吹竭@里,我們可能會有些疑惑,照理說,C++是強類型的語言,對類型的檢查應該是非常嚴格的,但是,我們將fish類的對象fh的地址直接賦給指向animal類的指針變量,C++編譯器居然不報錯。這是因為fish對象也是一個animal對象,將fish類型轉(zhuǎn)換為animal類型不用強制類型轉(zhuǎn)換,C++編譯器會自動進行這種轉(zhuǎn)換。反過來,則不能把animal對象看成是fish對象,如果一個animal對象確實是fish對象,那么在程序中需要進行強制類型轉(zhuǎn)換,這樣編譯才不會報錯。
            讀者可以猜想一下例2-16運行的結(jié)果,輸出的結(jié)果應該是“animal breathe”,還是“fish bubble”呢?
            為什么輸出的結(jié)果不是“fish bubble”呢?這是因為在我們將fish類的對象fh的地址賦給pAn時,C++編譯器進行了類型轉(zhuǎn)換,此時C++編譯器認為變量pAn保存就是animal對象的地址。當在fn函數(shù)中執(zhí)行pAn->breathe()時,調(diào)用的當然就是animal對象的breathe函數(shù)。
            為了幫助讀者更好地理解對象類型的轉(zhuǎn)換,我們給出了fish對象內(nèi)存模型。
            當我們構(gòu)造fish類的對象時,首先要調(diào)用animal類的構(gòu)造函數(shù)去構(gòu)造animal類的對象,然后才調(diào)用fish類的構(gòu)造函數(shù)完成自身部分的構(gòu)造,從而拼接出一個完整的fish對象。當我們將fish類的對象轉(zhuǎn)換為animal類型時,該對象就被認為是原對象整個內(nèi)存模型的上半部分,也就是圖2.13中的“animal的對象所占內(nèi)存”。當我們利用類型轉(zhuǎn)換后的對象指針去調(diào)用它的方法時,自然也就是調(diào)用它所在的內(nèi)存中的方法。因此,出現(xiàn)如圖2.12所示的結(jié)果,也就順理成章了。
            現(xiàn)在我們在animal類的breathe()方法前面加上一個virtual關(guān)鍵字,結(jié)果如例2-17所示。
            例2-17
            #include
            class animal
            {
            public:
            void eat()
            {
            cout<<"animal eat"<    }
            void sleep()
            {
            cout<<"animal sleep"<    }
            virtual void breathe()
            {
            cout<<"animal breathe"<    }
            };
            class fish:public animal
            {
            public:
            void breathe()
            {
            cout<<"fish bubble"<    }
            };
            void fn(animal *pAn)
            {
            pAn->breathe();
            }
            void main()
            {
            animal *pAn;
            fish fh;
            pAn=&fh;
            fn(pAn);
            }
            用virtual關(guān)鍵字申明的函數(shù)叫做虛函數(shù)。運行例2-17這個程序,結(jié)果調(diào)用的是fish類的呼吸方法:
            這就是C++中的多態(tài)性。當C++編譯器在編譯的時候,發(fā)現(xiàn)animal類的breathe()函數(shù)是虛函數(shù),這個時候C++就會采用遲綁定(late binding)技術(shù)。也就是編譯時并不確定具體調(diào)用的函數(shù),而是在運行時,依據(jù)對象的類型(在程序中,我們傳遞的fish類對象的地址)來確認調(diào)用的是哪一個函數(shù),這種能力就叫做C++的多態(tài)性。我們沒有在breathe()函數(shù)前加virtual關(guān)鍵字時,C++編譯器在編譯時就確定了哪個函數(shù)被調(diào)用,這叫做早期綁定(early binding)。
            C++的多態(tài)性是通過遲綁定技術(shù)來實現(xiàn)的,關(guān)于遲綁定技術(shù),讀者可以參看相關(guān)的書籍,在這里,我們就不深入講解了。
            C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運行時將會根據(jù)對象的實際類型來調(diào)用相應的函數(shù)。如果對象類型是派生類,就調(diào)用派生類的函數(shù);如果對象類型是基類,就調(diào)用基類的函數(shù)。