在 C++ 物件導向設計中,純虛函數與抽象基類是實現介面導向程式設計、達成多型與解耦的核心機制。本文將詳細說明其語法、語意、限制與實務應用。
純虛函數是在基類中宣告但不提供定義(實作)的虛函數,語法為在函數宣告尾端加上 = 0。
class Shape {
public:
virtual void draw() = 0; // 純虛函數
virtual ~Shape() = default; // 虛擬解構子
};
關鍵特性:
包含至少一個純虛函數的類別即為抽象基類。其特性:
Shape s; 編譯錯誤)| 特性 | 虛函數 | 純虛函數 |
|---|---|---|
| 語法 | virtual void f(); | virtual void f() = 0; |
| 定義 | 必須提供(即使不使用) | 可不提供 |
| 衍生類別 | 可選擇性覆寫 | 必須覆寫(否則仍為抽象類別) |
| 實例化 | 基類可實例化 | 基類不可實例化 |
/* CppPrimer.cpp
* Created on: 2013.11.12
* Author: Caroline
* Compiler: eclipse cdt
*/
#include <iostream>
#include <string>
using namespace std;
// 抽象基類
class Animal {
public:
virtual void speak() = 0; // 純虛函數
virtual ~Animal() = default;
};
// 具體衍生類別
class Dog : public Animal {
public:
void speak() override { cout << "汪汪!" << endl; }
};
class Cat : public Animal {
public:
void speak() override { cout << "喵~" << endl; }
};
void makeSound(Animal& a) {
a.speak(); // 多型呼叫
}
int main() {
Dog dog;
Cat cat;
makeSound(dog); // 輸出:汪汪!
makeSound(cat); // 輸出:喵~
// Animal a; // 編譯錯誤:抽象類別無法實例化
return 0;
}
雖然罕見,但純虛函數可以有定義,通常用於基類預設行為供衍生類別呼叫:
class Base {
virtual void init() = 0;
};
void Base::init() { // 提供定義
cout << "Base initialization" << endl;
}
class Derived : public Base {
void init() override { Base::init(); cout << "Derived init" << endl; }
};
基類解構子應宣告為虛擬,若為純虛則必須提供定義:
class Base {
virtual ~Base() = 0; // 純虛解構子
};
Base::~Base() {} // 必須提供定義
override (C++11) 明確表達覆寫意圖純虛函數定義了「契約」,抽象基類提供了「介面」。兩者結合讓 C++ 支援介面導向設計,實現執行期多型,是建構可擴充、低耦合系統的基石。