真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系

這篇文章主要講解了“C++ 多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C++ 多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系”吧!

成都創(chuàng)新互聯(lián)是一家專業(yè)提供北辰企業(yè)網(wǎng)站建設,專注與成都網(wǎng)站設計、成都網(wǎng)站建設、外貿網(wǎng)站建設H5頁面制作、小程序制作等業(yè)務。10年已為北辰眾多企業(yè)、政府機構等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站設計公司優(yōu)惠進行中。

多態(tài)與虛函數(shù)

面向對象編程中,多態(tài)的含義是“一個接口,多種實現(xiàn)”。
多態(tài)分為靜態(tài)多態(tài)和動態(tài)多態(tài)。靜態(tài)多態(tài)是通過模板化和重載技術來實現(xiàn),在編譯的時候確定。動態(tài)多態(tài)通過虛函數(shù)和繼承關系來實現(xiàn),執(zhí)行動態(tài)綁定,在運行的時候確定。
C++中運行時的多態(tài)是指根據(jù)對象的實際類型來調用相應的函數(shù)。如果對象類型是派生類,就調用派生類的函數(shù);如果對象類型是基類,就調用基類的函數(shù)。
C++多態(tài)性是通過虛函數(shù)來實現(xiàn)的,虛函數(shù)允許子類重新定義成員函數(shù),而子類重新定義父類方法稱為覆蓋或重寫(override)。

虛函數(shù):
用virtual關鍵字申明的函數(shù)叫做虛函數(shù),虛函數(shù)肯定是類的成員函數(shù)。
虛函數(shù)的作用就是實現(xiàn)動態(tài)綁定,也就是在程序的運行階段動態(tài)地選擇合適的成員函數(shù)。
具體的實現(xiàn)方式,在基類中定義了虛函數(shù)后,可以在基類的派生類中對虛函數(shù)重新定義,在派生類中重新定義的函數(shù)應與虛函數(shù)具有相同的形參個數(shù)和形參類型,以實現(xiàn)統(tǒng)一的接口,不同定義過程。
如果在派生類中沒有對虛函數(shù)重新定義,則它繼承其基類的虛函數(shù),此時派生類也為抽象類,不能實例化對象。

虛函數(shù)表:
當一個類含有一個乃至多個虛函數(shù)的時候,將在全局數(shù)據(jù)區(qū)(靜態(tài)區(qū))中存儲該類相應的虛函數(shù)表vtbl,編譯器給類的每個對象添加一個相同隱藏的成員——虛函數(shù)表指針vptr,指向自身類的虛函數(shù)表。
虛函數(shù)表的大小在編譯時確定,不必動態(tài)分配內存空間進行存儲,因此不虛函數(shù)表不存在堆中,根據(jù)以上特征,虛函數(shù)表類似于類中靜態(tài)成員變量。靜態(tài)成員變量也是全局共享,大小確定,所以虛函數(shù)表和靜態(tài)成員變量一樣,存放在全局數(shù)據(jù)區(qū)。
虛函數(shù)表中保存了類對象進行聲明的虛函數(shù)的地址,即虛函數(shù)表的元素是指向類成員函數(shù)的指針。也就是說我們可以通過vptr訪問虛函數(shù)表,進而訪問被聲明的虛函數(shù)的的地址,從而調用相應的虛函數(shù)。
同一個類的不同對象的vptr實際上指向同一張?zhí)摵瘮?shù)表。vptr的設定和重置都由每一個類的構造函數(shù),析構函數(shù)和拷貝賦值運算符自動完成。一般來說,將在構造函數(shù)中進行虛表的創(chuàng)建和虛表指針的初始化。
基類的虛函數(shù)表和派生類的虛函數(shù)表分別為保存在不同位置的兩個獨立數(shù)組,也就是說基類的隱藏成員和派生類的隱藏成員指向不同的地址。
如果派生類沒有重新定義基類的某個虛函數(shù)A,則派生類的虛函數(shù)表vtbl將保存基類的虛函數(shù)A的原始地址(此時派生類和基類的虛函數(shù)表中保存的虛函數(shù)A的地址是一樣的)。
如果派生類重寫了基類的某個虛函數(shù)B,則派生類的虛函數(shù)表vtbl將保存新的虛函數(shù)B的地址(此時的虛函數(shù)B其實有兩個版本,分別被基類和派生類的虛函數(shù)表分開保存)。

純虛函數(shù):
純虛函數(shù)是在基類中聲明的虛函數(shù),它在基類中沒有定義,要求任何派生類都要定義自己的實現(xiàn)方法。在基類中實現(xiàn)純虛函數(shù)的方法是在函數(shù)原型后加“=0”,即virtual void funtion1() = 0;
含有純虛函數(shù)的類為抽象類,不能聲明對象,只是作為基類為派生類服務。除非在派生類中完全實現(xiàn)基類的所有虛函數(shù),否則派生類也是抽象類,不能實例化對象。
抽象類不能定義對象,但是可以作為指針或引用類型使用。

不能聲明虛函數(shù):
常見的不能聲明為虛函數(shù)的有:普通函數(shù)(非成員函數(shù));靜態(tài)成員函數(shù);內聯(lián)成員函數(shù);構造函數(shù);友元函數(shù)。
普通函數(shù)(非成員函數(shù))只能被overload,不能被override,聲明為虛函數(shù)也沒有意義。
靜態(tài)成員函數(shù)對于每個類來說只有一份代碼,所有的對象都共享這一份代碼,也沒有要動態(tài)綁定的必要性。
內聯(lián)函數(shù)在編譯時被展開,從而可減少函數(shù)調用花費的代價,虛函數(shù)是在運行時才進行動態(tài)綁定,從而使得繼承對象能夠準確的執(zhí)行自己的動作。
構造函數(shù)目的是為了生成對象時進行對象初始化,虛函數(shù)目的是在不同類型的對象中調用不同的方法以產(chǎn)生不同的動作,當對象還沒有生成時,虛函數(shù)是沒有意義的,而構造函數(shù)是為了在對象還沒有生成時實例化對象。
友元函數(shù)不支持繼承,對于沒有繼承特性的函數(shù)就沒有虛函數(shù)的說法。

早綁定和晚綁定:
c++編譯器在編譯的時候,要確定每個對象調用的函數(shù)(非虛函數(shù))的地址,這稱為早期綁定,當我們將Son類對象的地址賦給指針pFather時,C++編譯器進行了類型轉換,此時C++編譯器認為指針變量pFather保存的就是Father對象的地址,當在main函數(shù)中執(zhí)行pFather->Say(),調用的是Father對象的Say函數(shù)。
從內存角度看:

C++ 多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系

前面輸出的結果是因為編譯器在編譯的時候,就已經(jīng)確定了對象調用的函數(shù)地址,要解決這個問題就要使用晚綁定,當編譯器使用晚綁定時候,就會在運行時再去確定對象的類型以及正確的調用函數(shù),而要讓編譯器采用晚綁定,就要在基類中聲明函數(shù)時使用virtual關鍵字.一旦某個函數(shù)在基類中聲明為virtual,那么在所有的派生類中該函數(shù)都是virtual,而不需要再顯式地聲明為virtual。

編譯器為每個對象提供了一個虛表指針(即vptr),這個指針指向了對象所屬類的虛表,在程序運行時,根據(jù)對象的類型去初始化vptr,從而讓vptr正確的指向了所屬類的虛表,從而在調用虛函數(shù)的時候,能夠找到正確的函數(shù)。由于pFather實際指向的對象類型是Son,因此vptr指向的Son類的vtable,當調用pFather->Son()時,根據(jù)虛表中的函數(shù)地址找到的就是Son類的Say()函數(shù)。
從內存角度看:

在這里插入圖片描述

構造函數(shù)與虛函數(shù)

構造函數(shù)不能為虛函數(shù)。
從C++之父Bjarne的回答我們應該知道C++為什么不支持構造函數(shù)是虛函數(shù)了,簡單講就是沒有意義。
虛函數(shù)的作用在于通過子類的指針或引用來調用父類的那個成員函數(shù)。而構造函數(shù)是在創(chuàng)建對象時自己主動調用的,不可能通過子類的指針或引用去調用。

構造函數(shù)目的是為了生成對象時進行對象初始化,虛函數(shù)目的是在不同類型的對象中調用不同的方法以產(chǎn)生不同的動作,當對象還沒有生成時,內存中不存在虛函數(shù)指針和虛函數(shù)表,此時虛函數(shù)是沒有意義的,而構造函數(shù)是為了在對象還沒有生成時實例化對象,如果構造函數(shù)被聲明為虛函數(shù),內存空間還沒有虛函數(shù)表,該構造函數(shù)將變得沒有意義,所以構造函數(shù)不能是虛函數(shù)。

析構函數(shù)與虛函數(shù)

當派生類指針指向用new運算符生成的派生類對象時,delete派生類指針,將執(zhí)行派生類的析構函數(shù),再執(zhí)行基類的析構函數(shù)。因為在實例化派生類對象時,先實例了基類對象。
當基類指針指向用new運算符生成的派生類對象時,delete基類指針,因為編譯器又進行了類型轉換,默認為基類指針指向基類對象的地址,根據(jù)早綁定中內存的關系,如果基類析構函數(shù)沒有聲明為虛函數(shù),將只執(zhí)行基類的構造函數(shù),如果基類析構函數(shù)聲明為虛函數(shù),盡管進行類型轉換,根據(jù)晚綁定中內存的關系,不管基類對象還是派生類對象都有相應的虛函數(shù)表指針,因此析構時會先調用派生類的析構函數(shù)(vptr指向自身的析構函數(shù)),再調用基類的析構函數(shù)(聲明派生類對象先實例了基類對象)。

#include
using namespace std;

class Base {
public:
    Base()
    { 
        cout<<"Base::Base()"<

感謝各位的閱讀,以上就是“C++ 多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系”的內容了,經(jīng)過本文的學習后,相信大家對C++ 多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!


當前名稱:C++多態(tài)與虛函數(shù)、與構造函數(shù)和析構函數(shù)有什么聯(lián)系
本文地址:http://weahome.cn/article/giopoi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部