友元:非類成員、非派生類,但被授權訪問類的 private/protected 成員。關鍵字 friend。
class Student {
friend void show(Student* p); // 聲明友元
private:
char* m_name; int m_age; float m_score;
};
void show(Student* p) { // 非成員函數
cout << p->m_name << " " << p->m_age << " " << p->m_score << endl;
}
關鍵:友元函數無 this 指針,必須通過參數傳遞物件(指針/引用/值)。
class Address; // 前向聲明
class Student {
public:
void show(Address* addr); // 成員函數
private:
char* m_name; int m_age; float m_score;
};
class Address {
friend void Student::show(Address*); // 聲明 Student::show 為友元
private:
char* m_province, *m_city, *m_district;
};
void Student::show(Address* addr) {
cout << m_name << " " << m_age << " " << m_score << endl;
cout << addr->m_province << addr->m_city << addr->m_district << endl; // 訪問 Address private
}
前向聲明必要性:類定義前使用另一類型(指針/引用/參數)需前向聲明;但建構物件需完整定義(編譯器需知大小)。
class Address {
friend class Student; // 整個 Student 類為友元
private:
char* m_province, *m_city, *m_district;
};
// Student 所有成員函數均可訪問 Address private 成員
優缺點:簡化聲明,但過度授權,安全性降低。優先用友元函數精確授權。
class Complex {
friend Complex operator+(const Complex&, const Complex&);
friend ostream& operator<<(ostream&, const Complex&);
friend istream& operator>>(istream&, Complex&);
private:
double m_real, m_imag;
};
運算符重載常為全域函數,需訪問私有成員 → 必須友元。
| 場景 | 傳統友元 | 現代替代 |
|---|---|---|
| 運算符重載 | friend | 公共介面 get_real() + 非友元全域函數 |
| 緊密協作類 | friend class | PIMPL 惯用法、介面隔離、組合 |
| 單元測試 | friend test class | 測試專用公共介面、FRIEND_TEST 宏 |