class Base
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
顯然,Base
將被派生。那麼,C++是否說編譯器生成的Base
的析構函數必須是虛擬的?抽象基類的編譯器生成的析構函數是虛擬的嗎?
謝謝!
class Base
{
virtual void foo() = 0;
//~Base(); <-- No destructor!
};
顯然,Base
將被派生。那麼,C++是否說編譯器生成的Base
的析構函數必須是虛擬的?抽象基類的編譯器生成的析構函數是虛擬的嗎?
謝謝!
不,解析器不會是virtual
,除非您將它標記爲這樣。原因很簡單 - 通過指針和通過引用幾乎可以進行調用,以及虛擬調用的方式和方式與是否使用new
創建對象無關。如果你不用new
創建對象,你不需要delete
它們,所以你不需要虛擬析構函數。
不,dtor不保證是虛擬的。
當聲明專門設計爲派生類的類時,其明確聲明虛擬Dtor的良好實踐。這通常是一個徹頭徹尾的設計缺陷。事實上,我不能想到這樣一種情況,它不是從基礎類中遺漏虛擬dtor的設計缺陷。
某些類可以被設計成派生自但不是多態使用(例如'boost :: noncopyable')。在這種情況下,提供虛擬析構函數是沒有意義的。 –
@Luc:在這種情況下,保護基類析構函數是個好主意,以防止無效的多態刪除。 –
當然,這是真的。我在考慮問題的背景,這是一個ABC。 –
它沒有。這是接近的證明,析構函數不會自動發虛:
#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」。
當然,它實際上並沒有證明有關標準的任何事情。您運行它的任何實現可能都是不合格的。但是一旦你嘗試了幾次,你會發現無論標準可能會說什麼,你都需要指定一個虛擬析構函數。
我在鍵盤上測試過:http://codepad.org/oMs4Kuye(g ++ 4.1.2),並且不按照預期打印「〜Derived」。無論是在我的MSVC2008。感謝這個例子。 –
不。一個班級可以有虛擬成員,可以派生出來,甚至可以用new
進行分配,也可以用delete
刪除,而不需要虛擬析構函數。
如果析構函數未聲明爲虛擬的,那麼非法(UB)要做的是使用指向基址的delete
銷燬派生實例。
當然,如果您的類是要派生的,沒有理由不聲明虛擬析構函數。
不,但我不能給你一個標準的*不*說的東西的參考... –
如果只有編譯器纔可以在stackoverflow上回答問題;) – MerickOWA