建構函式不能為虛函式,析構函式要為虛函式

2021-06-21 00:12:04 字數 2497 閱讀 4288

1,從儲存空間角度

虛函式對應乙個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函式。

2,從使用角度

虛函式主要用於在資訊不全的情況下,能使過載的函式得到對應的呼叫。建構函式本身就是要初始化例項,那使用虛函式也沒有實際意義呀。所以建構函式沒有必要是虛函式。

虛函式的作用在於通過父類的指標或者引用來呼叫它的時候能夠變成呼叫子類的那個成員函式

。而建構函式是在建立物件時自動呼叫的,不可能通過父類的指標或者引用去呼叫,因此也就規定建構函式不能是虛函式。

3、建構函式不需要是虛函式,也不允許是虛函式,因為建立乙個物件時我們總是要明確指定物件的型別,儘管我們可能通過實驗室的基類的指標或引用去訪問它。但析構卻不一定,我們往往通過基類的指標來銷毀物件。這時候如果析構函式不是虛函式,就不能正確識別物件型別從而不能正確呼叫析構函式。

4、從實現上看,vbtl在構造函式呼叫後才建立,因而建構函式不可能成為虛函式 

從實際含義上看,在呼叫建構函式時還不能確定物件的真實型別(因為子類會調父類的建構函式);而且建構函式的作用是提供初始化,在物件生命期只執行一次,不是物件的動態行為,也沒有太大的必要成為虛函式

5、當乙個建構函式被呼叫時,它做的首要的事情之一是初始化它的v p t r。因此,它只能知道它是「當前」類的,而完全忽視這個物件後面是否還有繼承者。當編譯器為這個建構函式產生**時,它是為這個類的建構函式產生**- -既不是為基類,也不是為它的派生類(因為類不知道誰繼承它)。

所以它使用的v p t r必須是對於這個類的v ta b l e。而且,只要它是最後的構造函式呼叫,那麼在這個物件的生命期內, v p t r將保持被初始化為指向這個v ta b l e, 但如果接著還有乙個更晚派生的建構函式被呼叫,這個建構函式又將設定v p t r指向它的 v ta b l e,等.直到最後的建構函式結束。v p t r的狀態是由被最後呼叫的建構函式確定的。這就是為什麼構造函式呼叫是從基類到更加派生 類順序的另乙個理由。

但是,當這一系列構造函式呼叫正發生時,每個建構函式都已經設定v p t r指向它自己的 v ta b l e。如果函式呼叫使用虛機制,它將只產生通過它自己的v ta b l e的呼叫,而不是最後的v ta b l e(所有建構函式被呼叫後才會有最後的v ta b l e)。

析構函式為虛函式:

當派生類的物件從記憶體中撤銷時一般先呼叫派生類的析構函式,然後再呼叫基類的析構函式。但是,如果用new運算子建立了臨時物件,若基類中有析構函式,並且定義了乙個指向該基類的指標變數。在程式用帶指標引數的delete運算子撤銷物件時,會發生乙個情況:系統會只執行基類的析構函式,而不執行派生類的析構函式。

例12.3 基類中有非虛析構函式時的執**況。

為簡化程式,只列出最必要的部分。

#include

using namespace std;

class point//定義基類point類

//point類建構函式

~point();

class circle:public point//定義派生類circle類

//circle類建構函式

~circle( );

int main( )

這只是乙個示意的程式。p是指向基類的指標變數,指向new開闢的動態儲存空間,希望用detele釋放p所指向的空間。但執行結果為:

executing point destructor

表示只執行了基類point的析構函式,而沒有執行派生類circle的析構函式。原因是以前介紹過的。

如果希望能執行派生類circle的析構函式,可以將基類的析構函式宣告為虛析構函式,如

virtual ~point(){cout<<″executing point destructor″<

程式其他部分不改動,再執行程式,結果為

executing circle destructor

executing point destructor

先呼叫了派生類的析構函式,再呼叫了基類的析構函式,符合人們的願望。

當基類的析構函式為虛函式時,無論指標指的是同一類族中的哪乙個類物件,系統會採用動態關聯,呼叫相應的析構函式,對該物件進行清理工作。

如果將基類的析構函式宣告為虛函式時,由該基類所派生的所有派生類的析構函式也都自動成為虛函式,即使派生類的析構函式與基類的析構函式名字不相同。

最好把基類的析構函式宣告為虛函式。這將使所有派生類的析構函式自動成為虛函式。

這樣,如果程式中顯式地用了delete運算子準備刪除乙個物件,而delete運算子的操作物件用了指向派生類物件的基類指標,則系統會呼叫相應類的析構函式。

虛析構函式的概念和用法很簡單,但它在物件導向程式設計中卻是很重要的技巧。

專業人員一般都習慣宣告虛析構函式,即使基類並不需要析構函式,也顯式地定義乙個函式體為空的虛析構函式,以保證在撤銷動態分配空間時能得到正確的處理。

建構函式不能宣告為虛函式。這是因為在執行建構函式時類物件還未完成建立過程,當然談不上函式與類物件的繫結。

建構函式不能為虛函式

1,從儲存空間角度 虛函式對應乙個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函式。2,從使用角度 虛函式主要用...

建構函式 析構函式 虛析構函式

說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...

建構函式 析構函式 虛函式

在類中,建構函式用於初始化物件及相關操作。建構函式是不能宣告為虛函式的,因為虛函式對應乙個virtual table 虛函式表 這個表的位址是儲存在物件的記憶體空間的。而在執行建構函式前,物件尚未完成建立,記憶體都沒有被分配,所以無法去查詢虛函式表,它不存在,因此也就無法得知該呼叫哪乙個函式了。析構...