我們知道需要虛擬析構函數。運行時多態的構造函數行爲
Base *bptr = new Derived();
delete bptr;
如果一個派生類對象是由一個基類指針和當對象超出範圍指出,只有基類的析構函數被調用,除非析構函數是虛擬的。
我想知道在這種情況下構造函數是如何正確工作的。 由於Base指針指向Derived對象,因此只有Base構造函數應該被調用。它如何正確調用派生類的構造函數。
請解釋一下背後的原因。
我們知道需要虛擬析構函數。運行時多態的構造函數行爲
Base *bptr = new Derived();
delete bptr;
如果一個派生類對象是由一個基類指針和當對象超出範圍指出,只有基類的析構函數被調用,除非析構函數是虛擬的。
我想知道在這種情況下構造函數是如何正確工作的。 由於Base指針指向Derived對象,因此只有Base構造函數應該被調用。它如何正確調用派生類的構造函數。
請解釋一下背後的原因。
在用new
創建對象時,我們有完整信息的對象;
new Derived(); // static type is same as dynamic type
您分配指針的LHS部分是無關緊要的。這就是爲什麼你不需要這種構造函數的機制。有關更多信息,請參閱Bjarne Stroustrup的頁面。
其他說明,virtual
需要析構函數,因爲您正在使用指向delete
對象的指針。
delete bptr; // static type may not be same as dynamic type
new Derived()在任何地方都沒有基類引用。你可以選擇甚至把它分配給什麼。因此,得到的指針分配給什麼不會影響構造。
當您執行以下操作:
Base *bptr = new Derived();
要調用的new
運營商爲Derived
類,因爲這是你正在構建什麼。
當您將new
返回的Derived*
指定給Base*
時,您只需上傳指針,該指針是隱式操作。
您明確地說要構建的Derived
一個實例:
Base *bptr = new Derived();
手段請構造一個對象,如果類型class Derived
,然後請一個指針存儲到該對象bptr
。所以編譯器有沒有什麼可猜測或推斷。
new Derived();
創建的class Derived
和泄漏該對象的對象:
與它比較。編譯器在這裏也沒什麼可猜測或推論的。這兩個片段之間的唯一區別是前者存儲指針,後者不存在。
「如果派生類對象被基類指針指向,並且對象超出作用域,則只有基類析構函數被調用,除非析構函數是虛擬的。」 - 如果派生類的對象超出範圍,則派生類析構函數被調用,並且任何其他正常指針的存在和類型都是不相關的。如果一個正常的指針指向任何東西超出範圍,則不會調用任何東西。智能指針可以調用析構函數,在這種情況下,虛擬調度的確是必需的,以確保它是派生類的派生類。 'new X'雖然沒有範圍。 –
感謝您的更正。實際上,我的意思是說,當「刪除bptr」被執行時,只有基類析構函數被調用,除非析構函數是虛擬的。 – user166002