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

C++ 類別分解與抽象類:純虛函數的必要性與介面契約設計

     編輯:關於C++

類別分解:從抽象到具體的層層細化

繼承本質是**結構擴張與特性分解**:基類定義共同協議,派生類逐步具體化差異點。


// 交通工具層次
class Vehicle {        // 抽象概念:速度、載重
    float speed; int total;
public:
    Vehicle(float s, int t) : speed(s), total(t) {}
    virtual void Show() = 0;  // 純虛函數:強制派生類實現
};

class Car : public Vehicle {  // 具體化:增加空氣排量
    int airDisp;
public:
    Car(int ad, float s, int t) : Vehicle(s, t), airDisp(ad) {}
    void Show() override { cout << speed << "|" << total << "|" << airDisp; }
};

class Plane : public Vehicle {  // 另一種具體化:增加飛行高度
    int altitude;
public:
    Plane(int alt, float s, int t) : Vehicle(s, t), altitude(alt) {}
    void Show() override { cout << speed << "|" << total << "|" << altitude; }
};

純虛函數與抽象類:強制介面契約

語法與規則


class AbstractBase {
public:
    virtual void Interface() = 0;  // 純虛函數:無實現、=0 標記
    virtual ~AbstractBase() {}     // 虛解構函數:刪除基類指標時正確調用派生解構
};

// 錯誤:AbstractBase obj;  // 編譯錯誤:抽象類不能實例化
// 正確:AbstractBase *ptr = new Derived();

核心作用

  1. 語意標記:明確告知「此類為介面/協議,不可直接使用,必須繼承實現」。
  2. 編譯期強制:派生類**必須**覆寫所有純虛函數,否則派生類仍為抽象類。
  3. 多態基石:基類指標/引用統一調用派生類實現,實現運行期綁定。

純虛函數的三種進階用法

1. 純虛解構函數:抽象類必備


class Base {
public:
    virtual ~Base() = 0;  // 純虛解構
};
Base::~Base() {}  // **必須提供定義**,因為派生類解構時會調用基類解構
// 若無定義 → 連結錯誤

2. 純虛函數提供預設實現:模板方法模式


class Algorithm {
public:
    void Run() { Step1(); Step2(); Step3(); }  // 非虛:固定流程
private:
    virtual void Step1() = 0;  // 子類必須實現
    virtual void Step2() { cout << "Default Step2"; }  // 虛函數有預設實現
    virtual void Step3() = 0;
};

3. 介面類別 (Interface Class):純虛函數集合


class ISerializable {  // 命名慣例:I 前綴
public:
    virtual ~ISerializable() {}
    virtual void Save(ostream&) const = 0;
    virtual void Load(istream&) = 0;
};

class Document : public ISerializable { /* 實現序列化 */ };
class Image : public ISerializable { /* 實現序列化 */ };

void SerializeAll(const vector& objs, ostream& out) {
    for (auto p : objs) p->Save(out);  // 統一介面,多態調用
}

抽象類 vs 介面類別 vs 具體類

類別類型純虛函數資料成員構造函數可實例化典型用途
介面類別全部無 (或僅 static const)預設/保護否定義契約、多重實現、插件架構
抽象基類部分可有 (共享狀態)保護否提供通用實現、模板方法、部分介面
具體類無任意公有是最終產品、值型別

現代 C++ 介面設計最佳實踐

  1. 介面類別盡量純粹:無資料成員、無建構函數參數、虛解構函數、所有方法純虛。
  2. 基類解構函數必須 virtual (public 繼承時),否則 delete basePtr 僅調用基類解構 → 資源洩漏。
  3. 用 override (C++11) 明確標記覆寫意圖,編譯器檢查簽名匹配。
  4. 用 final (C++11) 禁止進一步覆寫/繼承,優化虛函數調用 (devirtualization)。
  5. 傾向組合而非繼承:class Car { Engine engine; } 優於 class Car : public Engine。
  6. 依賴倒置原則 (DIP)**:高層模組依賴抽象介面,低層模組實現介面,雙方不依賴具體類。

常見誤區對比

誤區正確理解
純虛函數不能有函數體**可以有** (如純虛解構函數),但派生類仍需覆寫 (解構函數除外,自動鏈式調用)
抽象類不能有構造函數**可以有** (通常為 protected),供派生類構造時初始化基類部分
介面類別應定義為 struct慣例用 class + public:,語意更清晰;struct 成員預設 public 易誤用
多重繼承介面類別會有菱形問題介面類別**無資料成員**,菱形繼承不產生重複資料,**無需虛擬繼承**

總結

  1. 類別分解是**由抽象到具體**的層層細化,純虛函數是標記「必須由派生類實現」的編譯期契約。
  2. 抽象類 (含純虛函數) **不可實例化**,僅作為基類指標/引用的靜態型別。
  3. 介面類別 (全純虛、無資料) 是現代 C++ 多態設計的核心,支援多重實現、插件架構、依賴倒置。
  4. 虛解構函數是**多態刪除的生命線**,抽象類必須定義 (哪怕是純虛)。
  5. 善用 override/final、組合優於繼承、DIP 原則,構建可維護、可擴展、可測試的類別體系。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved