乙個類的虛函式在它自己的建構函式和析構函式中被呼叫的時候,它們就變成普通函式了,不「虛」了。也就是說不能在建構函式和析構函式中讓自己「多型」。例如:
class a
// 在這裡,無論如何都是a::foo()被呼叫!
~a() // 同上
virtual void foo();
};class b: public a
;void bar()
如果你希望delete a的時候,會導致b::foo()被呼叫,那麼你就錯了。同樣,在new b的時候,a的建構函式被呼叫,但是在a的建構函式中,被呼叫的是a::foo()而不是b::foo()。為什麼會有這樣的規定呢,原因如下:
當基類被構造時,物件還不是乙個派生類的物件,所以如果base::base()呼叫了虛函式virt(),則base::virt() 將被呼叫,即使derived::virt()(派生類重寫該虛函式)存在。
同樣,當基類被析構時,物件已經不再是乙個派生類物件了,所以如果base::~base()呼叫了virt(),則base::virt()得到控制權,而不是重寫的derived::virt() 。
當你可以想象到如果derived::virt() 涉及到派生類的某個成員物件將造成的災難的時候,你很快就能看到這種方法的明智。詳細來說,如果base::base()呼叫了虛函式virt(),這個規則使得base::virt()被呼叫。如果不按照這個規則,derived::virt()將在派生物件的派生部分被構造之前被呼叫,此時屬於派生物件的派生部分的某個成員物件還沒有被構造,而derived::virt()卻能夠訪問它。這將是災難。
建構函式 析構函式 虛析構函式
說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...
建構函式 析構函式 虛函式
在類中,建構函式用於初始化物件及相關操作。建構函式是不能宣告為虛函式的,因為虛函式對應乙個virtual table 虛函式表 這個表的位址是儲存在物件的記憶體空間的。而在執行建構函式前,物件尚未完成建立,記憶體都沒有被分配,所以無法去查詢虛函式表,它不存在,因此也就無法得知該呼叫哪乙個函式了。析構...
C 建構函式 析構函式 虛析構函式
一般地,建立物件和刪除物件時,父類建構函式 子類建構函式 子類析構函式 父類析構函式。特例 如果用new建立了乙個物件,並將父類的指標指向這個子類的物件,那麼用delete撤銷物件時,系統只執行基類的析構函式,而不執行派生類的析構函式。如果希望按照子類析構函式 父類析構函式的順序執行,那麼應該將基類...