原則上, 類的私有(private)和受保護(protected)成員不能從聲明它們的同一類外部訪問。但是, 此規則不適用於友元 "friends"。
以friend關鍵字修飾的函數或類稱為友元函數或友元類。
友元函數
友元函數是可以直接訪問類的私有成員的非成員函數。它是定義在類外的普通函數,它不屬於任何類,但需要在類的定義中加以聲明,聲明時只需在友元的名稱前加上關鍵字friend,其格式如下:
friend 類型 函數名(形式參數);
友元函數的聲明可以放在類的私有部分,也可以放在公有部分,它們是沒有區別的,都說明是該類的一個友元函數。
一個函數可以是多個類的友元函數,只需要在各個類中分別聲明。
友元函數的調用與一般函數的調用方式和原理一致。
友元類
友元類的所有成員函數都是另一個類的友元函數,都可以訪問另一個類中的隱藏信息(包括私有成員和保護成員)。
當希望一個類可以存取另一個類的私有成員時,可以將該類聲明為另一類的友元類。定義友元類的語句格式如下:
friend class 類名;
其中:friend和class是關鍵字,類名必須是程序中的一個已定義過的類。
綜合例子
#include <iostream> using namespace std; class Square; class Rectangle { private: int m_nWidth; int m_nHeight; public: Rectangle() {} Rectangle (int nX, int nY) : m_nWidth(nX), m_nHeight(nY) {} int area() {return m_nWidth * m_nHeight;} friend Rectangle duplicate (const Rectangle&); // friend functions void convert (Square a); }; Rectangle duplicate (const Rectangle& param) { Rectangle res; res.m_nWidth = param.m_nWidth*2; res.m_nHeight = param.m_nHeight*2; return res; } class Square { friend class Rectangle; // friend class private: int side; public: Square (int a) : side(a) {} }; void Rectangle::convert (Square a) { m_nWidth = a.side; m_nHeight = a.side; } int main () { Rectangle foo; Rectangle bar (2,3); foo = duplicate (bar); cout << foo.area() << endl; Rectangle rect; Square sqr (4); rect.convert(sqr); cout << rect.area() << endl; return 0; }
說明:
duplicate
函數為類Rectangle的一個友元函數,可以訪問該類的不同對象的私有成員m_nWidth和m_nHeight,形式上看duplicate
聲明為該類的一個成員函數,但是其僅僅有該類私有成員的訪問權限而已,並不是該類的一個成員函數!
類Rectangle為類Square
的一個友元類,則允許類Rectangle的成員函數可以訪問類Square
的私有或保護成員,本例中訪問了類Square
的私有成員變量side。
使用友元類時注意:
1、友元關系不能被繼承。
2、友元關系是單向的,不具有交換性。若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應的聲明。
3、友元關系具有非傳遞性。若類B是類A的友元,類C是B的友元,類C不一定是類A的友元,同樣要看類中是否有相應的申明。