2011-08-12 34 views
5
class Base 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

顯然,Base將被派生。那麼,C++是否說編譯器生成的Base的析構函數必須是虛擬的?抽象基類的編譯器生成的析構函數是虛擬的嗎?

謝謝!

+3

不,但我不能給你一個標準的*不*說的東西的參考... –

+2

如果只有編譯器纔可以在stackoverflow上回答問題;) – MerickOWA

回答

6

不,解析器不會是virtual,除非您將它標記爲這樣。原因很簡單 - 通過指針和通過引用幾乎可以進行調用,以及虛擬調用的方式和方式與是否使用new創建對象無關。如果你不用new創建對象,你不需要delete它們,所以你不需要虛擬析構函數。

1

不,dtor不保證是虛擬的。

當聲明專門設計爲派生類的類時,其明確聲明虛擬Dtor的良好實踐。這通常是一個徹頭徹尾的設計缺陷。事實上,我不能想到這樣一種情況,它不是從基礎類中遺漏虛擬dtor的設計缺陷。

+2

某些類可以被設計成派生自但不是多態使用(例如'boost :: noncopyable')。在這種情況下,提供虛擬析構函數是沒有意義的。 –

+0

@Luc:在這種情況下,保護基類析構函數是個好主意,以防止無效的多態刪除。 –

+0

當然,這是真的。我在考慮問題的背景,這是一個ABC。 –

2

它沒有。這是接近的證明,析構函數不會自動發虛:

#include <iostream> 

struct BaseBase { 
    ~BaseBase() { 
     std::cout << "~BaseBase\n"; 
    } 
}; 

struct Base : BaseBase 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

struct Derived : Base { 
    void foo() { std::cout << "foo\n"; } 
    ~Derived() { 
     std::cout << "~Derived\n"; 
    } 
}; 

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

這個程序實際上是未定義行爲,但我強烈懷疑您的實現不打印「〜派生」。如果Base有一個虛擬析構函數,那麼它將不會有未定義的行爲,並且會打印「〜Derived」。

當然,它實際上並沒有證明有關標準的任何事情。您運行它的任何實現可能都是不合格的。但是一旦你嘗試了幾次,你會發現無論標準可能會說什麼,你都需要指定一個虛擬析構函數。

+0

我在鍵盤上測試過:http://codepad.org/oMs4Kuye(g ++ 4.1.2),並且不按照預期打印「〜Derived」。無論是在我的MSVC2008。感謝這個例子。 –

1

不。一個班級可以有虛擬成員,可以派生出來,甚至可以用new進行分配,也可以用delete刪除,而不需要虛擬析構函數。

如果析構函數未聲明爲虛擬的,那麼非法(UB)要做的是使用指向基址的delete銷燬派生實例。

當然,如果您的類是要派生的,沒有理由不聲明虛擬析構函數。

相關問題