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

C++ 解構函式奧秘:隱含呼叫順序與虛擬解構函式必要性

     編輯:關於C++

解構函式的呼叫順序與虛擬機制是 C++ 記憶體管理的核心。本文透過實測程式碼,揭示編譯器隱含插入的解構函式呼叫順序,並說明為何基類別解構函式必須宣告為 virtual 以避免記憶體洩漏。

案例一:聚合物件的自動解構


class A { 
public: 
    A() { pValue = new int[100]; printf("Constructor of A\n"); }
    ~A() { delete[] pValue; printf("Deconstructor of A\n"); }
private: int* pValue; 
};
class B { public: ~B() { printf("Deconstructor of B\n"); } };
class C : public B { 
public: ~C() { printf("Deconstructor of C\n"); }
private: A a; 
};
int main() { C c; return 0; }

輸出順序:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

編譯器隱含在 C::~C() 中呼叫 a.~A(),再呼叫基類別 B::~B()。若成員是指標而非物件,編譯器不會自動呼叫 delete。

案例二:基類別指標刪除衍生物件的陷阱


int main() { B* b = new C; delete b; }

輸出僅:

Constructor of A
Deconstructor of B

C::~C() 與 A::~A() 均未被呼叫,導致 new int[100] 記憶體洩漏。原因:delete b 靜態綁定至 B::~B()。

解決方案:虛擬解構函式


class B { public: virtual ~B() { ... } };
class C : public B { public: virtual ~C() { ... } };

再次執行,輸出正確:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

虛擬解構函式確保 delete 透過虛函數表動態綁定至實際物件類型的解構函式,完整釋放資源。

核心結論

  • 編譯器自動為基類別子物件與聚合成員物件插入解構呼叫。
  • 指標成員需手動 delete,編譯器不介入。
  • 凡可能被基類別指標刪除的類別,解構函式必須宣告 virtual。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved