2016-07-16 24 views
0

鑑於此程序:如何刪除具有派生類對象中沒有dstructor

struct Base 
{ 
    virtual void f() {} 
}; 

struct Derived:public Base 
{ 
}; 

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

GCC-4.4 -Wall是好的,但GCC-5.2 -Wall給出了警告:派生態類型」的刪除對象'具有非虛擬析構函數可能會導致未定義的行爲[-Wdelete-non-virtual-dtor]

我看到了the discussion on deleting a base pointer但在我的情況下,它是派生的對象。我認爲這是一個海灣合作委員會的錯誤,但顯然GNU doesn't think so。有沒有辦法在不改變基類定義的情況下襬脫警告?

+1

該代碼是正確的;你可以忽略這個警告。 –

回答

2

GCC有權發出該警告。爲什麼?因爲除非您聲明Derivedfinal,否則有人可能會創建類型,該類型源自Derived。此時,刪除指針Derived可能非常無效。

virtual析構函數添加到Base並沒有真正的缺點。是的,析構函數將是一個虛擬的調用。但這不會成爲性能瓶頸。

+0

在派生類中添加「final」可以解決問題。我無法更改供應商提供的基類。那麼,我想我可以改變.h但不是.so。幾個無關緊要但相關的問題:1.如果沒有〜Base(),我可以安全地添加「virtual〜Base(){}」嗎? 2.如果在Base中有非虛擬dtor,我可以安全地添加虛擬嗎? – zhao

+1

你的供應商真的應該解決這個問題,這是一個很大的禁止在C + +和一個普通的求職面試問題, –

+0

不,警告是錯誤的。無論是否有'MoreDerived'類型,指針對象的類型都是「Derived」,並且在顯示的上下文中刪除它沒有問題。當然,在另一種情況下,警告是正確的,但這不是這種情況。 –

0

向Base添加virtual ~Base() {}將修復警告。

因此會將final添加到派生。

class Derived final : public Base 
{ 
    ... 
}; 

所以將一個虛擬析構函數添加到派生。

class Derived : public Base 
{ 
public: 
    virtual ~Derived() {} 

    ... 
}; 

此外,如果您不打算使用派生多態,您可以私下繼承。這不會阻止警告,但是您永遠不能將Derived指針指定給Base指針,因此永遠不會通過Base指針刪除Derived。

class Derived : private Base 
{ 
    ... 
}; 
+0

我知道代碼是100%合法的,按預期工作,並且沒有未定義的行爲。同時,有時人們希望擺脫代碼中的所有警告。由於GCC可能不會改變警告,因此需要其他解決方案。 – evan

+0

是的,對不起。堅持從另一個答案。你的問題只是直接回答問題,解釋如何擺脫警告。我刪除了我的評論。 –