虛函數是 C++ 實現執行期多型的核心,抽象類則定義了介面契約。本文系統講解虛函數作用、使用方法、限制、虛解構子必要性、純虛函數語意與抽象類設計模式,附完整程式碼驗證。
class Time { public: void show() { cout << "Time"; } };
class LocalTime : public Time { public: void show() { cout << "LocalTime"; } };
Time* pt = new LocalTime;
pt->show(); // 輸出 "Time" - 靜態繫結到 Time::show()
基類指標指向衍生物件,呼叫非虛函數時依指標型別而非物件型別決定。
class Time { public: virtual void show() { cout << "Time"; } };
// LocalTime 不變
Time* pt = new LocalTime;
pt->show(); // 輸出 "LocalTime" - 動態繫結
編譯器在衍生類別物件中放置虛函數表指標 (vptr),指向該類別的虛函數表 (vtable),執行時查表繫結。
virtual 宣告Base*,衍生類別可回傳 Derived*| 限制 | 說明 |
|---|---|
| 僅限成員函數 | 非成員函數不可為虛函數 |
| 不可為 static | 靜態成員無 this 指標,屬於類別非物件 |
| 不可為 inline | 內聯需編譯期確定位址,虛函數需執行期查表 |
| 建構子不可虛 | 建構時 vptr 尚未初始化,物件型別確定 |
| 空間開銷 | 每類別一 vtable,每物件一 vptr (通常 4/8 bytes) |
class Time { public: ~Time() { cout << "Time dtor"; } };
class LocalTime : public Time { public: ~LocalTime() { cout << "LocalTime dtor"; } };
Time* p = new LocalTime;
delete p; // 僅輸出 "Time dtor" - 衍生解構子未呼叫,資源洩漏
class Time { public: virtual ~Time() { cout << "Time dtor"; } };
// 輸出:LocalTime dtor -> Time dtor (正確順序)
鐵律:只要類別有虛函數,解構子必須宣告為 virtual。
class Shape {
public:
virtual void draw() = 0; // 純虛函數:無函數體,=0 僅標記
virtual ~Shape() = default;
};
Base::func() 呼叫)
#include
#include
using namespace std;
class Time {
public:
Time(int h=0,int m=0,int s=0):hour(h),min(m),sec(s) {}
virtual void show() { cout << hour << ":" << min << ":" << sec << endl; }
virtual ~Time() { cout << "Time destructor" << endl; }
protected:
int hour, min, sec;
};
class LocalTime : public Time {
public:
LocalTime(int h=0,int m=0,int s=0,string z="+8"):Time(h,m,s),zone(z) {}
void show() override { cout << hour << ":" << min << ":" << sec << "@" << zone << endl; }
~LocalTime() { cout << "LocalTime destructor" << endl; }
protected:
string zone;
};
int main() {
Time t;
LocalTime lt;
Time* pt = &t;
pt->show(); // 0:0:0
pt = <
pt->show(); // 0:0:0@+8 動態繫結
Time* p = new LocalTime;
delete p; // LocalTime destructor -> Time destructor
return 0;
}
虛函數實現「一個介面,多種實作」;虛解構子保證資源正確釋放;純虛函數定義抽象契約;抽象類承載介面規格。掌握這套機制,是 C++ 物件導向設計進階的關鍵門檻。