2012-03-29 178 views
2

如果我們沒有虛擬構造函數,那麼爲什麼我們有虛擬析構函數?構造函數也可以是虛擬的嗎?沒有虛擬構造函數但是虛擬析構函數

+0

可能的重複[爲什麼我們在C++中沒有虛擬構造函數?](http://stackoverflow.com/questions/733360/why-do-we-not-have-a-virtual-constructor-in- c) – 2012-03-29 10:58:42

+1

@TomaszNurkiewicz:我認爲問題是,我們爲什麼在C++中有虛擬析構函數? – 2012-03-29 11:01:13

回答

16
  • 在虛擬構造函數中沒有任何意義 - 您聲明瞭 類型的創建方式,它在編譯時是衆所周知的。編譯器 不需要[實際上不能,因爲動態調度基於 關於僅在創建對象之後創建的信息]。 所以沒有虛擬構造函數
  • 虛擬析構函數對於防止內存泄漏非常重要,並且 監視系統。假設你有A* a = new B; [BA繼承 ],你後來delete a; - 編譯器無法 知道a的方式是B [在一般情況下],並調用A的 析構函數 - 如果它是不虛擬的,你可能會得到內存泄漏, 或其他故障。
  • 使用虛擬析構函數 - 你確保B的析構函數被調用,因爲B對象被銷燬。因爲在銷燬時需要
+0

我不明白第一點。請你詳細說明一下。 – devsda 2012-09-19 12:23:05

+1

@jhamb:當你調用構造函數時 - 它就像'new MyClass;'一樣。創建對象的*動態類型*和靜態類型*完全相同,即真實的具體對象。 – amit 2012-09-19 19:53:41

2

虛析構函數,你並不總是知道什麼類型的你正在處理:

Base *make_me_an_object() 
{ 
    if (the_moon_is_full()) 
     return new Derived(); 
    else 
     return new Base(); 
} 

int main() 
{ 
    Base *p = make_me_an_object(); 
    delete p; 
} 

中的delete上述程序的main不知道其是否p指向BaseDerived對象,但如果Base析構函數爲virtual(應該是),則delete可以使用*pvtable來查找正確的析構函數。

相比之下,在建造時,你總是知道你正在創建什麼樣的對象。 (而如果你不這樣做,那麼你可以創建一個工廠或「virtual constructor」,它知道。)

0
#include<iostream> 
using namespace std; 
class base { 
    protected: 
    int a; 
}; 
class derived : public base { 

}; 
int main() { 
    base * pointer_of_base = new derived; 
    delete pointer_of_base; // this will delete the base calss not the derived 

} 

的構造函數的調用上一次當我們創建類,所以當我們繼承的對象基類構造函數只調用一次,所以不需要虛擬。但是當我們從基類的指針訪問派生類時,如果我們想要刪除派生類的對象,我們通過基類的指針刪除它,但是刪除(pointer_of_base)將調用基類的析構函數但實際的座右銘是刪除派生類。因此我們需要析構函數在本質上是虛擬的。