當類別 `B` 的成員函數需作為類別 `A` 的友元,且 `B` 定義在 `A` 之後,會遇到「不完整型別」編譯錯誤。解決關鍵:**前向宣告 + 友元宣告完整簽名 + 定義延後**。
class A {
friend void B::foo(); // 錯誤:B 尚未定義,B::foo 不完整
};
class B {
public:
void foo() {}
};
// 1. 前向宣告 B
class B;
// 2. A 宣告友元 (需完整簽名)
class A {
friend void B::foo(); // 此處 B 已宣告,但 foo 定義尚未見 → 允許
private:
int data_;
};
// 3. B 定義 (含 foo 實作)
class B {
public:
void foo() {
A a;
a.data_ = 42; // 可存取 A 私有成員
}
};
class A {
friend void B::staticFoo(); // 同樣只需前向宣告 B
};
class B {
public:
static void staticFoo() { /* ... */ }
};
class A {
friend class B; // B 所有成員皆為 A 友元
// ...
};
| 場景 | 前向宣告 | 友元宣告位置 | 定義順序 |
|---|---|---|---|
| B::foo() 友元 A | `class B;` | A 內部 | A 定義前,B 定義後 |
| B 整個類別友元 A | `class B;` | A 內部 `friend class B;` | 同上 |
| A::foo() 友元 B | `class A;` | B 內部 | B 定義前,A 定義後 |
掌握「前向宣告 + 友元完整簽名 + 定義延後」模式,即可解決所有成員函數友元的編譯順序問題。