每個含有虛函式的類都會有至少乙個對應的虛函式表。其記憶體布局為虛函式指標、類內成員變數,其中虛函式指標指向虛函式表(構造過程為:1.拷貝父類虛函式,2.替換子類重寫的父類虛函式3.新增子類獨有的虛函式)
執行 base *base = new base(); 當 delete base時,會呼叫析構函式為我們釋放資源。而 我們執行base *son = new son(); 如果base基類的析構函式不是虛函式的時候,delete son 物件的時候,只會釋放base基類申請的資源,而不是釋放son派生類的資源。原因如下:(總結:將可能會被繼承的父類的析構函式設定為虛函式,可以保證當我們new乙個子類,然後使用基類指標指向該子類物件,釋放基類指標時可以釋放掉子類的空間,防止記憶體洩漏。)
基類指標指向了派生類物件,而基類中的析構函式是非virtual的,而虛構函式是動態繫結的基礎。現在析構函式不是virtual的,因此不會發生動態繫結,而是靜態繫結,指標的靜態型別為基類指標,因此在delete的時候只會呼叫基類的析構函式,而不會呼叫派生類的析構函式。這樣,在派生類中申請的資源就不會得到釋放,就會造成記憶體洩漏,這是相當危險的:如果系統中有大量的派生類物件被這樣建立和銷毀,就會有記憶體不斷的洩漏,久而久之,系統就會因為缺少記憶體而崩潰。
因為虛函式需要額外的虛函式表,虛函式指標,占用了額外的記憶體。只有當需要作為父類的時候才會去考慮建構函式寫成虛函式
儲存空間角度:虛函式對應乙個vtable,vtable儲存於物件的記憶體空間,若建構函式是虛的,則需要通過 vtable來呼叫,若物件還未例項化,即記憶體空間還沒有,無法找到vtable,陷入死迴圈,出錯。
使用角度:虛函式主要用於在資訊不全的情況下,能使過載的函式得到對應的呼叫。
建構函式本身就是要初始化例項,那使用虛函式就沒有實際意義
從實際含義上看,在呼叫建構函式時還不能確定物件的真實型別(因為子類會調父類的建構函式);而且建構函式的作用是提供初始化,在物件生命期只執行一次,不是物件的動態行為,也沒有太大的必要成為虛函式
,vptr先指向父類的虛函式表,在父類構造完成之後,子類的vptr才指向自己的虛函式表。也就是說,在父類或者子類的建構函式中呼叫虛成員函式是沒有多型性的。
純虛函式可以提供抽象類的功能,抽象類則通常提供統一介面的功能,
強迫繼承它的派生類各自實現符合自己特點的具體功能,並且一定要有這樣的功能,這對於設計和架構非常有用
C 建構函式 析構函式 虛析構函式
一般地,建立物件和刪除物件時,父類建構函式 子類建構函式 子類析構函式 父類析構函式。特例 如果用new建立了乙個物件,並將父類的指標指向這個子類的物件,那麼用delete撤銷物件時,系統只執行基類的析構函式,而不執行派生類的析構函式。如果希望按照子類析構函式 父類析構函式的順序執行,那麼應該將基類...
建構函式 析構函式 虛析構函式
說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...
建構函式 析構函式 虛函式
在類中,建構函式用於初始化物件及相關操作。建構函式是不能宣告為虛函式的,因為虛函式對應乙個virtual table 虛函式表 這個表的位址是儲存在物件的記憶體空間的。而在執行建構函式前,物件尚未完成建立,記憶體都沒有被分配,所以無法去查詢虛函式表,它不存在,因此也就無法得知該呼叫哪乙個函式了。析構...