首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ 虛析構函數完全指南:何時需要、為什麼需要、純虛析構怎麼寫

     編輯:關於C語言

核心問題:基類指針刪除派生類對象的資源洩漏

class Base { public: Base(); ~Base(); ... };
class Derived : public Base { ... };

Base* p = new Derived;
delete p;  // 危險!若 Base::~Base() 非虛,只調用 Base 析構,Derived 析構不被調用 → 資源洩漏

鐵律:多態基類必須擁有虛析構函數

凡是擁有虛函數的類(即設計為多態基類),其析構函數必須聲明為 virtual。

  • 虛函數表機制:對象包含 vptr 指向 vtable,析構同樣需動態分發。
  • delete p 通過 vptr 找到正確的析構函數入口,保證「最深層派生類 → 基類」順序調用。
  • 無虛函數的類(如 std::string、std::vector)不應加虛析構,否則每個對象多佔指針大小內存,違背「不為不用的特性付費」原則。

純虛析構函數:抽象類的特殊形態

為什麼需要純虛析構?

當類沒有任何純虛成員函數,但仍想強制其為抽象類(不可實例化),只能將析構函數聲明為純虛:

class Test {
public:
    virtual ~Test() = 0;  // 純虛析構
};

關鍵陷阱:純虛析構必須提供定義


// 必須在類外提供定義,否則鏈接報錯 "undefined reference to Test::~Test()"
Test::~Test() { }  // 空實現即可

原因:派生類析構時會隱式調用基類析構,編譯器在派生類析構函數中插入 Base::~Base() 調用指令,鏈接階段必須找到符號。

析構調用順序鐵律

派生類構造:  基類構造 → 成員構造 → 派生類構造體
派生類析構:  派生類析構體 → 成員析構 → 基類析構(遞歸向上)

虛析構保證此順序在運行時通過 vtable 正確執行。

最佳實踐清單

場景析構函數聲明說明
多態基類(有虛函數)virtual ~Base()必須,防止 delete 基類指針洩漏
非多態具體類~Concrete()非虛,零開銷
強制抽象類(無其他純虛)virtual ~Abstract() = 0; + 類外定義純虛析構需定義,否則鏈接失敗
接口類(全純虛)virtual ~Interface() = default;C++11 默認實現,簡潔明確

總結

虛析構不是可選裝飾,是多態類型系統的基石。 記住三句口訣:
1. 有 virtual 就要 virtual ~()。
2. 純虛 ~() 必須寫定義。
3. 非多態類別加 virtual ~() 會多佔 8 字節(64位),得不償失。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved