2011-02-03 128 views
0

我很難決定在這裏刪除我的派生類的最佳方式。目前,我有以下佈局:去哪裏?

class Tag { 
    // Stuff 
    // [...] 
    void releaseMemory(Tag *t); 
}; 

class TagByte : public Tag { /* [...] */ }; 
class TagShort : public Tag { /* [...] */ }; 

Tag::releaseMemory(Tag *t) { 
    switch (t->getType()) { 
     case TAG_BYTE: delete (TagByte *)t; return; 
     case TAG_SHORT: delete (TagShort *)t; return; 
     // [...] many more 
    } 
} 

的原因,我這樣做是有更復雜的標籤,如TagCompound其中將包含不同類型的標籤,而所有這些都存儲爲Tag *。破壞者內部~TagCompound,~TagList我確實在每個標籤上都打Tag::releaseMemory();,因爲deleteTag *上只會釋放Tag而不是實際的TagWhatever,從而導致內存泄漏。

我想到的另一個選擇是爲每個派生類添加一個新的虛擬方法,因此Tag的每個子都會擁有它自己的releaseMemory(),而不是在超類中組合的一個。

然後,我不知道我是否已經開始關閉在設計水平差假設一切傳遞到複雜類型TagCompoundTagList對象,而我還沒有找到更好的解決辦法,因爲這整個構造的東西是一個分析器看起來像這樣(只是二進制而不是詳細)的一部分:

TAG_Compound("Root"): 4 entries 
{ 
    TAG_String("Name"): Test 
    TAG_Short("SomeNumber"): 21 
    TAG_Double("..."): 9000.5 
    TAG_Compound("Eek!"): 2 entries 
    { 
    TAG_String("Marco"): Polo 
    TAG_List("Names"): 3 entries of type String 
    { 
     TAG_String: Hello 
     TAG_String: World 
     TAG_String: Segfault 
    } 
    } 
} 

,動態讀取運行時不會與棧上的實例發揮出色。

我該怎麼做才能做到這一點...我不知道..優雅?

+0

爲什麼不使用overloded releaseMemory成員函數?我認爲如果我的問題得到解決就足夠了。 – Arunmu 2011-02-03 04:13:11

回答

5

一般來說,你只需要declare a virtual destructor in the base class。這對堆棧和堆分配都很有幫助。在多態刪除的情況下,編譯器會計算出真正的類型並調用它的析構函數。

+0

這實際上比我所做的要複雜得多,謝謝:) – LukeN 2011-02-03 05:13:02

1

這個設計真的打破了封裝的想法。標籤不應該知道TagByte存在。 Tag的析構函數應該像每個派生類的析構函數一樣被標記爲虛擬的。釋放適當析構函數中每個級別的分配變量。在銷燬時,所有內容都將按照正確的順序清理,不會造成內存泄漏。我的感覺是這種設計從一開始就不好,你應該閱讀析構函數和繼承。

+0

是的,我也這麼認爲,這就是爲什麼我決定更好地問問知道更好的人! – LukeN 2011-02-03 04:15:53

1

C++實際上提供了非常優雅的解決方案 - 虛擬析構函數。更多的是,每​​個多態類型都應該有一個。 GCC甚至對此-Wnon-virtual-dtor有警告級別。