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

C++ 虛析構函數與純虛析構函數深度解析

     編輯:關於C++

為什麼析構函數要聲明為 virtual?

當通過基類指針刪除派生類對象時,若基類析構函數非虛函數,則只會調用基類析構函數,導致派生類資源洩漏。聲明為 virtual 後,delete 會觸發動態綁定,依次調用派生類與基類析構函數,實現多態鏈式銷毀。

class Base { public: virtual ~Base() {} };
class Derived : public Base { public: ~Derived() {} };
Base *pb = new Derived;
delete pb; // 正確調用 ~Derived() 再 ~Base()

純虛析構函數:可行但必須提供定義

將析構函數聲明為純虛函數(virtual ~Base() = 0;)可使類成為抽象類,禁止實例化。但必須提供函數體,否則鏈接階段報錯「unresolved external symbol」。

原因:派生類析構函數隱含調用基類析構函數,編譯器需要基類析構函數的實際代碼地址。純虛僅表示「派生類必須重寫」,不代表「無定義」。

class Base {
public:
    virtual ~Base() = 0; // 聲明純虛
};
Base::~Base() {}         // 必須在類外提供定義(不能內聯寫在類內)

純虛函數也可以有函數體

純虛函數(=0)的語義是「強制派生類實現」,而非「無實現」。基類仍可提供默認實現供派生類調用:

class Base {
public:
    virtual void Hierarchy() const = 0;
};
void Base::Hierarchy() const { cout << "Base::Hierarchy"; } // 提供默認實現

class Derived : public Base {
public:
    void Hierarchy() const override {
        Base::Hierarchy(); // 顯式調用基類實現
        cout << "Derived::Hierarchy";
    }
};

虛函數常見問題總結

問題結論
構造函數能否為虛函數?不能。構造時對象尚未完全形成,虛表指針未就緒。
構造函數中調用虛函數會怎樣?執行基類版本(多態被禁用),因派生類部分未構造。
析構函數可以是純虛嗎?可以,但必須提供定義體。
純虛函數是否一定無函數體?不,可以有函數體,甚至可被顯式調用。
override 時返回類型能否協變?僅當返回類型為指針/引用且指向派生類時允許(如 Clone 模式)。

設計哲學:為什麼 C++ 用純虛函數而非 abstract class 關鍵字?

Stroustrup 指出:純虛函數更靈活,允許分階段定義類。中間層類只需關注自身職責,無需知道是否已實現所有祖先的純虛函數,也無需在類級別聲明 abstract。這對複雜繼承體系尤為重要。

最佳實踐建議

  • 所有作為基類用途的類,**析構函數必須聲明為 virtual**。
  • 若需禁止基類實例化且無其他合適純虛函數,可將析構函數設為純虛,**但務必在類外提供空定義**。
  • C++11 起使用 override 關鍵字,編譯器將檢查簽名一致性,防止隱藏而非覆蓋。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved