首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 基礎

C++ friend 友元函數與友元類:打破封裝邊界的受控訪問機制

     編輯:C++ 基礎

友元核心概念

友元:非類成員、非派生類,但被授權訪問類的 private/protected 成員。關鍵字 friend。

  • 單向:A 是 B 友元 ≠ B 是 A 友元
  • 不傳遞:A 是 B 友元,B 是 C 友元 ≠ A 是 C 友元
  • 破壞封裝:慎用,僅在必要時(運算符重載、緊密協作類、測試代碼)

友元函數兩種形式

1. 非成員函數(全域/命名空間函數)

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 指針,必須通過參數傳遞物件(指針/引用/值)。

2. 其他類的成員函數

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;
};

運算符重載常為全域函數,需訪問私有成員 → 必須友元。

現代 C++ 替代方案:減少友元使用

最佳實踐檢查清單

  1. 能不友元就不友元:優先公共介面、getter/setter
  2. 精確授權:友元函數優於友元類
  3. 文檔說明:註釋為何需要友元(如運算符重載對稱性)
  4. 避免循環依賴:友元常導致頭文件互相包含,善用前向聲明

總結

friend 是 C++ 打破封裝的受控後門:友元函數(非成員/他類成員)與友元類(整類授權)。核心特性:單向、不傳遞、破壞封裝。經典用於運算符重載對稱性、緊密協作類。現代 C++ 傾向最小化友元,通過介面設計、PIMPL、組合替代。掌握友元機制是為了讀懂標準庫/舊代碼,新代碼請三思而後用。

  1. 上一篇文章:
  2. 下一篇文章:
  • --热点文章
  • Copyright © 程式碼之家 All Rights Reserved
    場景傳統友元現代替代
    運算符重載friend公共介面 get_real() + 非友元全域函數
    緊密協作類friend classPIMPL 惯用法、介面隔離、組合
    單元測試friend test class測試專用公共介面、FRIEND_TEST 宏