純虛函數語法與語義
virtual 返回型別 函數名(參數列表) = 0;
= 0 為純虛標記,非返回值
- 無函數體,僅聲明
- 告訴編譯器:「派生類必須實現此函數」
抽象類定義與特性
- 包含至少一個純虛函數的類稱為抽象類
- 無法實例化(不能建構物件)
- 通常作為基類/介面使用
- 派生類必須實現所有繼承的純虛函數才能實例化
實戰:幾何形狀繼承體系
#include <iostream>
using namespace std;
// 抽象基類:線段
class Line {
public:
Line(float len) : m_len(len) {}
virtual float area() = 0; // 純虛:線無面積
virtual float volume() = 0; // 純虛:線無體積
protected:
float m_len;
};
// 矩形:實現 area()
class Rect : public Line {
public:
Rect(float len, float w) : Line(len), m_width(w) {}
float area() override { return m_len * m_width; }
protected:
float m_width;
};
// 長方體:實現 volume(),成為可實例化類
class Cuboid : public Rect {
public:
Cuboid(float l, float w, float h) : Rect(l, w), m_height(h) {}
float area() override {
return 2 * (m_len*m_width + m_len*m_height + m_width*m_height);
}
float volume() override { return m_len * m_width * m_height; }
protected:
float m_height;
};
// 正方體:繼承並可選擇覆寫
class Cube : public Cuboid {
public:
Cube(float len) : Cuboid(len, len, len) {}
float area() override { return 6 * m_len * m_len; }
float volume() override { return m_len * m_len * m_len; }
};
int main() {
Line* p = new Cuboid(10, 20, 30);
cout << "Cuboid 面積: " << p->area() << endl; // 2200
cout << "Cuboid 體積: " << p->volume() << endl; // 6000
p = new Cube(15);
cout << "Cube 面積: " << p->area() << endl; // 1350
cout << "Cube 體積: " << p->volume() << endl; // 3375
}
關鍵觀察
Line 為抽象類,定義介面契約(area()/volume())
Rect 實現 area(),但 volume() 仍為純虛 → Rect 仍為抽象類
Cuboid 實現 volume(),所有純虛函數皆有實現 → 首個可實例化類
- 基類指針
Line* 透過虛函數調用派生類實現 → 多態
純虛函數的雙重核心價值
| 價值 | 說明 |
| 介面契約/強制實現 | 基類定義「必須做什麼」,派生類負責「怎麼做」。違反者無法實例化,編譯期強制保證。 |
| 多態基石 | 基類指針/引用調用虛函數,動態綁定到派生類實現。無純虛函數則無法構成此多態體系。 |
純虛函數關鍵規則
- 僅虛函數可聲明為純虛,普通函數/頂層函數不可
- 抽象類可包含:純虛函數、普通虛函數、非虛函數、成員變數
- 純虛函數可以有定義(罕見,供派生類
Base::func()調用)
- 構造函數不能為虛函數/純虛;析構函數應為虛函數(非純虛)
現代 C++ 最佳實踐
- 使用
override 關鍵字(C++11)明確標記覆寫,編譯器檢查簽名一致性
- 介面類命名慣例:
IPrintable、Drawable 或純抽象類
- 組合優於繼承:純虛介面定義行為契約,具體實現用組合注入
- 避免過度設計:非多態場景無需純虛函數
總結
純虛函數(=0)與抽象類是 C++ 實現介面導向程式設計與運行時多態的核心機制。它們在編譯期強制派生類履行契約,在運行期實現基類指針對派生行為的動態分發。掌握「介面契約」與「多態基石」雙重語義,是設計可擴展、可維護 C++ 系統架構的關鍵。
- 上一篇文章: C++ typeid 運算符詳解:運行時類型識別 (RTTI) 核心機制
- 下一篇文章: C++ 虛函數深度解析:多態機制核心、覆寫規則與設計決策指南
Copyright ©
程式碼之家 All Rights Reserved