2011-07-09 42 views
12

由於boost::/std::shared_ptr有型擦除其刪除器的優勢,可以做好事像如果您始終將其存儲在shared_ptr中,那麼您的界面是否需要虛擬析構函數?

#include <memory> 

typedef std::shared_ptr<void> gc_ptr; 

int main(){ 
    gc_ptr p1 = new int(42); 
    gc_ptr p2 = new float(3.14159); 
    gc_ptr p3 = new char('o'); 
} 

而且所有指針感謝被保存了正確的缺失者,這將正確地刪除。

如果您確保您的界面的每個實現始終使用shared_ptr<Interface>(或make_shared<Interface>)創建,您實際上是否需要一個virtual析構函數?無論如何,我會聲明它爲virtual,但我只想知道,因爲shared_ptr將始終刪除它初始化的類型(除非給出另一個自定義刪除程序)。

+1

可能重複的[shared_ptr magic:)](http://stackoverflow.com/questions/3899790/shared-ptr-magic) –

+0

@Armen:這不是重複的,他不是問'shared_ptr'如何它,但是否應該使用虛擬析構函數*知道* shared_ptr具有這種魔力。 –

+1

@大衛:不,他沒有。他說他無論如何都會使用虛擬析構器。他問是否沒有一個。所以它是重複的 –

回答

12

我仍然會按照該是爲了派生類的通用規則:

提供任何公共虛析構函數或受保護的非虛擬析構函數

的原因是你無法控制所有用途,並且該簡單規則意味着如果您嘗試在層次結構中通過錯誤級別嘗試delete,編譯器將會標記。考慮到shared_ptr並不能保證它會調用相應的析構函數,只知道它會調用作爲參數的靜態類型的析構函數:

base* foo(); 
shared_ptr<base> p(foo()); 

如果base有一個公共非虛析構函數和foo回報來自base的類型,則shared_ptr將無法​​調用正確的析構函數。如果base的析構函數是虛擬的,那麼一切都會很好,如果它受到保護,編譯器會告訴你那裏有錯誤。

+0

「我會聲明它是虛擬的,[...]」。 :)關於無法控制所有實例化點的好處。儘管如此,你總是可以使用一個命名的構造函數,但這可能看起來不太好。 – Xeo

+1

警告:受保護的析構函數當前對'is_nothrow_destructible :: value'回答不正確,即使它們沒有拋出異常。爲此,我贊成公衆的選擇。 –

+0

@霍華德:感謝有關'is_nothrow_destructible'的信息。它似乎做對了。你爲什麼要讓它目前正確地報告「不可破壞」的事實,讓你改變可破壞的東西? –

相關問題