在類的外部,任何實例訪問類的 private 或 protected 成員都是被禁止的,這是出於安全性的考慮。但是很多時候,出於實用性的考慮,的確需要從外部訪問類的 private 或 protected 的成員,這可以在 C++ 中通過關鍵字 friend 來實現。 友元(friend)機制允許一個類將對其非公有成員(private 和 protected 成員)的訪問授予指定的函數或類。友元函數必須要在類的內部進行聲明,友元不是授予友元關系的那個類成員,出於編碼風格的考慮,通常將友元聲明橙組地放置在類定義的開頭或結尾處 一、全局函數作為友元 [cpp] // Friend_Global.cpp #include <iostream> using namespace std; class Base { int value; // 私有成員 protected: string str; // 保護成員 public: Base(const string newStr, const int ii) : str(newStr), value(ii) {} friend void view(Base&); // 聲明friend的全局函數 }; void view(Base& b) { // 接受的是基類對象 cout << "string = " << b.str << endl << "value = " << b.value << endl; return ; } int main() { Base b("Base", 49); view(b); /* // 任何實例,在類的外部試圖訪問 // 類的private或protected成員都是被禁止的 cout << "string = " << b.str << endl << "value = " << b.value << endl; */ return 0; } 運行結果: 值得注意的是,使用friend關鍵字修飾的全局函數void view(Base& b)並非是Base類的成員函數,它僅僅是全局函數 二、其它類的成員函數成為友元 [cpp] // Friend_Class.cpp #include <iostream> using namespace std; class Y; // 因為在類X中的view函數中出現了Y,因此必須事先聲明類Y class X { public: /* 參數類型聲明為指針,因為類Y的定義在下方, 在Y的定義之前,編譯器或許並不知道應該為Y的對象 分配多大的內存空間,而如果是Y*指針的話,編譯器 作了一次不完全的類型匹配,編譯器知道如何傳遞一個 地址,這一地址有具體的大小,而不管被傳遞的是什麼 對象,即使它還沒有完全知道這種對象類型的大小 雖然事實上傳遞對象也是可以的,但是在這種情況下, 傳遞一個對象的地址更為安全! */ void view(const Y*); }; class Y { int value; // 私有成員 protected: string str; // 保護成員 public: Y(const string newStr, const int ii) : str(newStr), value(ii) {} friend void X::view(const Y*); // 聲明friend的全局函數 }; void X::view(const Y* y) { cout << "string = " << y->str << endl << "value = " << y->value << endl; return ; } int main() { Y y("Base", 49); X x; x.view(&y); return 0; } 運行結果: