首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 虛解構函數機制深度解析:為什麼要用「父類指標指向子類物件」

     編輯:程式設計綜合問答

核心代碼示例

class A {
public:
    A() { cout << "A" << endl; }
    virtual ~A() { cout << "~A" << endl; }
};

class B : public A {
public:
    B() { cout << "B" << endl; }
    ~B() { cout << "~B" << endl; }
};

int main() {
    A* p = new B;  // 關鍵行
    delete p;
    return 0;
}

執行結果與解析

輸出:
A
B
~B
~A

關鍵點:由於 A 的解構函數宣告為 virtual,delete p 會正確調用 B::~B() 再調用 A::~A()。若非虛解構函數,僅調用 A::~A() 導致子類資源洩漏。

為什麼寫 A* p = new B 而非 A* p = new A?

1. 多型的核心體現

父類指標/引用指向子類物件,是 C++ 實現**執行時多型**的基礎。這允許:

  • 統一介面操作不同衍生類物件
  • 容器儲存異構物件:std::vector vec; vec.push_back(new B); vec.push_back(new C);
  • 工廠模式返回基類指標:A* createObject(int type) { if(type==1) return new B; ... }

2. 現實建模需求

例如圖形繪製系統:

class Shape { virtual void draw() = 0; virtual ~Shape() {} };
class Circle : public Shape { void draw() override { ... } };
class Rect : public Shape { void draw() override { ... } };

// 使用端無需知道具體類型
std::vector shapes;
shapes.push_back(new Circle);
shapes.push_back(new Rect);
for (auto s : shapes) s->draw();  // 多型調用
for (auto s : shapes) delete s;   // 虛解構確保正確釋放

3. 必須這樣寫的場景

記憶體佈局視角


// new B 記憶體結構
[ vptr -> B::vtable ]  // 虛函數表指標
[ A 的成員變數 ]
[ B 的成員變數 ]

// A* p 指向該記憶體起始位址
// delete p 透過 vptr 找到完整的解構函數鏈

最佳實踐鐵律

只要類別被設計為基類(有虛函數或預期被繼承),其解構函數必須宣告為 virtual。

  • C++11 可加 override 關鍵字增強編譯期檢查
  • 現代 C++ 偏好智慧指標(unique_ptr/shared_ptr)自動管理生命週期,避免手動 delete
  • 最終類別(final)可不宣告虛解構函數,但無害

總結

A* p = new B 不僅是語法合法,更是 C++ 物件導向設計「面向介面程式設計」的核心體現。虛解構函數確保多型刪除時資源正確釋放,是類別設計為基類時的**強制性契約**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景說明
插件架構主程式載入動態庫,僅知基類介面,實例化衍生類
策略模式執行時切換演算法實現(如排序、壓縮策略)
框架回調框架定義抽象基類,使用者繼承實現具體邏輯