菱形繼承(`A ← B, C → D`)會導致派生類 `D` 包含兩份基類 `A` 的成員,造成記憶體浪費與名稱二義性。虛繼承(`virtual public`)通過共享單一基類子物件完美解決此問題。本文以 `Person → Teacher/Student → Graduate` 為例,完整演示虛繼承語法、記憶體佈局與構造順序。
#include <iostream>
#include <string>
using namespace std;
// 間接基類
class Person {
protected:
int age;
char sex;
string name;
public:
Person(int a, char s, string n) : age(a), sex(s), name(n) {}
};
// 虛繼承:關鍵字 virtual
class Teacher : virtual public Person {
protected:
string title;
public:
Teacher(int a, char s, string n, string t) : Person(a, s, n), title(t) {}
};
class Student : virtual public Person {
protected:
float score;
public:
Student(int a, char s, string n, float sc) : Person(a, s, n), score(sc) {}
};
// 最終派生類:必須直接調用虛基類構造函數
class Graduate : public Teacher, public Student {
protected:
float wage;
public:
Graduate(int a, char s, string n, string t, float sc, float w)
: Person(a, s, n), // 必須顯式初始化虛基類
Teacher(a, s, n, t),
Student(a, s, n, sc),
wage(w) {}
void show() {
cout << name << endl;
cout << age << endl;
cout << sex << endl;
cout << title << endl;
cout << score << endl;
cout << wage << endl;
}
};
int main() {
Graduate gr(22, 'F', "Alice", "Professor", 89.5f, 79.5f);
gr.show();
return 0;
}
Alice 22 F Professor 89.5 79.5
非虛繼承記憶體佈局 (菱形) 虛繼承記憶體佈局
┌─────────────┐ ┌─────────────┐
│ Graduate │ │ Graduate │
├─────┬───────┤ ├─────┬───────┤
│Teacher │ │Teacher │
│ └ Person │ │ └ (vptr) │
├─────┼───────┤ ├─────┼───────┤
│Student │ │Student │
│ └ Person │ ← 兩份 Person! │ └ (vptr) │
└─────────────┘ └─────┬───────┘
│ Person (共享單份)
└─────────────┘