私有成員只能在類的成員函數內部訪問,若是想在別處訪問對象的私有成員,只能經過類提供的接口(成員函數)間接地進行。這當然可以帶來數據隱藏的好處,利於未來程序的擴充,但也會增長程序書寫的麻煩。
C++ 是從結構化的C語言發展而來的,須要照顧結構化設計程序員的習慣,因此在對私有成員可訪問範圍的問題上不可限制太死。
C++ 設計者認爲, 若是有的程序員真的很是怕麻煩,就是想在類的成員函數外部直接訪問對象的私有成員,那仍是作一點妥協以知足他們的願望爲好,這也算是眼前利益和長遠利益的折中。所以,C++ 就有了友元(friend)的概念。打個比方,這至關因而說:朋友是值得信任的,因此能夠對他們公開一些本身的隱私。
友元分爲兩種:友元函數和友元類。html
在定義一個類的時候,能夠把一些函數(包括全局函數和其餘類的成員函數)聲明爲「友元」,這樣那些函數就成爲該類的友元函數,在友元函數內部就能夠訪問該類對象的私有成員了。
將全局函數聲明爲友元的寫法以下:ios
friend 返回值類型 函數名(參數表);程序員
將其餘類的成員函數聲明爲友元的寫法以下:函數
friend 返回值類型 其餘類的類名::成員函數名(參數表);spa
可是,不能把其餘類的私有成員函數聲明爲友元。
關於友元,看下面的程序示例。.net
這個程序只是爲了展現友元的用法,因此 main 函數什麼也不作。
第 3 行聲明瞭 CCar 類,CCar 類的定義在後面。之因此要提早聲明,是由於 CDriver 類的定義中用到了 CCar 類型(第7行),而此時 CCar 類尚未定義,編譯會報錯。
不要第 3 行,而把 CCar 類的定義寫在 CDriver 類的前面,是解決不了這個問題的,由於 CCar 類中也用到了 CDriver 類型(第14行),把 CCar 類的定義寫在前面會致使第 14 行的 CDriver 因沒有定義而報錯。C++ 爲此提供的解決辦法是:能夠簡單地將一個類的名字提早聲明,寫法以下:設計
class 類名;指針
儘管能夠提早聲明,可是在一個類的定義出現以前,仍然不能有任何會致使該類對象被生成的語句。但使用該類的指針或引用是沒有問題的。
第 13 行將全局函數 MostExpensiveCar 聲明爲 CCar 類的友元,所以在第 24 行能夠訪問 cars[i] 的私有成員 price。同理,第 14 行將 CDriver 類的 ModifyCar 成員函數聲明爲友元,所以在第 18 行能夠訪問 pCar 指針所指向的對象的私有成員變量 price。htm
一個類 A 能夠將另外一個類 B 聲明爲本身的友元,類 B 的全部成員函數就均可以訪問類 A 對象的私有成員。在類定義中聲明友元類的寫法以下:對象
friend class 類名;
來看以下例程:
第 5 行將 CDriver 聲明爲 CCar 的友元類。這條語句原本就是在聲明 CDriver 是一個類,因此 CCar 類定義前面就不用聲明 CDriver 類了。第 5 行使得 CDriver 類的全部成員函數都能訪問 CCar 對象的私有成員。若是沒有第 5 行,第 13 行對 myCar 私有成員 price 的訪問就會致使編譯錯誤。 通常來講,類 A 將類 B 聲明爲友元類,則類 B 最好從邏輯上和類 A 有比較接近的關係。例如上面的例子,CDriver 表明司機,CCar 表明車,司機擁有車,因此 CDriver 類和 CCar 類從邏輯上來說關係比較密切,把 CDriver 類聲明爲 CCar 類的友元比較合理。 友元關係在類之間不能傳遞,即類 A 是類 B 的友元,類 B 是類 C 的友元,並不能導出類 A 是類 C 的友元。「咱倆是朋友,因此你的朋友就是個人朋友」這句話在 C++ 的友元關係上 不成立。