2014-02-20 38 views
0

最近我正在使用C++學習OOP,我很困惑時,我應該在以下情況下,用我自己的毀滅功能:什麼時候應該在C++中使用我自己的銷燬函數?

class T1{ 
private: 
    int data; 

public: 
    T1(){...}; 
    ~T1(){}; // should I write my own function here? 
}; 

class T2{ 
private: 
    T1* pointer_to_T1; 

public: 
    T2(){...}; 
    ~T2(){}; // should I write my own function here? 
}; 

class Node{ 
public: 
    int data; 
    Node* next; 
}; 

class T3{ 
private: 
    int size; 
    Node* head; 
public: 
    T3(size){ 
     head = new Node[size]; 
    } 
    ~T3(){}; // should I write my own function here? 
}; 

有在我的計劃上面澄清我的問題三點意見。我希望你能解釋他們,如果你能給我一條通則,我將不勝感激。

+0

不要忘記讓你的析構函數變成虛擬的。記住這一點非常重要! – Kieveli

回答

0

我會嘗試以一般方式回答,而不是針對您的代碼片段。

兩種常見的情況通常出現在你自己身上,你需要一個不平凡的析構函數。這不是一個完整的列表;只是最常見的情況。

1)在(多態)層次結構中。如果你的類是一個基類,打算從中派生,那麼你的基類應該有一個非平凡的析構函數是一個很好的機會。而且,那個析構函數應該可能是virtual。這使得有可能通過基類指針刪除派生類對象,像這樣:

class Foo 
{ 
public: 
    virtual ~Foo(){} 
}; 

class Bar : public Foo 
{ 
}; 

int main() 
{ 
    Foo* obj = new Bar; 
    delete obj; 
} 

沒有virtual析構函數,這個程序會表現出未定義行爲。

2)當你的班級成員需要的不僅僅是微不足道的破壞。一個簡單的例子是如果你的類有一個成員是一個使用new創建的原始指針(因爲不是智能指針)。該指針需要爲delete d,而析構函數可能是正確的地方。如果您的類具有複製構造函數或複製賦值運算符(operator=),則表明您的類管理的是非平凡破壞的成員。如果你的班級有,那麼它可能需要他們兩個加上一個析構函數來處理分配的任何東西。 (請參閱Rule of Three)然而,這不是唯一的跡象 - 你可以只有一個默認的構造函數,但仍然需要析構函數。這取決於你的班級做什麼。

0

類的析構函數應執行刪除對象時所需的所有操作。

例如,它需要釋放由該類動態分配的所有內存。

0

當你的類是一個基類時,你應該編寫一個析構函數,並且你期望多態破壞,並且當你希望在對象被銷燬時運行一些邏輯。

如果對象擁有和管理資源,您可能需要一個構造函數。不要忘記複製和分配操作符。

+0

那個析構函數應該是'虛擬的' –

1

class T3的情況下,你正在分配新的內存,所以你將不得不刪除分配的內存段的結構。

class T3{ 
private: 
    int size; 
    Node* head; 
public: 
    T3(size){ 
     head = new Node[size]; 
    } 
    ~T3(){ 
     delete[] head; 
     }; 
}; 
+0

現在你有無效的複製語義。你還應該按照[Rule of Three](http://stackoverflow.com/questions/4172722)實現或刪除複製構造函數和複製賦值運算符,或者更好的方法是使用'std :: vector'來管理數組自動。 –

0

對象應該自行清理。

IE,如果你曾經在對象中分配內存,可能在構造函數中完成,那麼你應該在析構函數中釋放內存。

析構函數是爲了清理你的對象。所以你也可以做任何事情來幫助你做到這一點。

0

T1類不需要顯式定義析構函數。只要編譯器隱式定義析構函數就足夠了。

類T2需要明確定義析構函數來釋放其具有類型指針的數據成員。否則會有內存泄漏。

類節點不需要明確定義析構函數。 T3類必須刪除類節點的所有指針,因爲它控制節點的分配和釋放。

+0

你怎麼知道T2擁有內存的成員指針地址? –

+0

@Luchian Grigore使用不屬於類的原始指針是一個糟糕的設計。 –

+0

那麼,在任何地方使用原始指針都是一個糟糕的設計......重點是 - 這是關於資源所有權的問題,而不是類是否有指針。它可能是一個文件句柄,不一定是一個指針。 –

0

你需要聲明析構函數:如果類管理需要時,它的破壞手動釋放的資源

  • ;
  • 如果它打算是一個多態基類,在這種情況下,它需要一個虛擬析構函數來允許多態刪除。

在第一種情況下,您還需要提供或刪除複製構造函數和複製賦值運算符;否則最終可能會有兩個或更多對象試圖管理相同的資源。這就是所謂的"Rule of Three"。通常,您可以使用容器和智能指針等現成的類爲您管理內存;所以通常不需要自己去解析析構函數。有人將此稱爲「零規則」。

在第二種情況下,析構函數不需要做任何事情(假設類沒有試圖管理任何資源),它只需要是虛擬的。

爲您具體的例子:

  • T1不需要析構函數
  • T2威力,取決於它是否是應該管理什麼指針指向。如果是,請考慮用智能指針替換指針,如std::unique_ptr<T1>
  • T3可能會,因爲它似乎是管理動態數組。你還需要考慮三條規則;或考慮使用std::vector<Node>自動管理陣列。
相關問題